diff --git a/Apps/Sandcastle/gallery/Labels.html b/Apps/Sandcastle/gallery/Labels.html index 2c4b4b4b7f96..aaf32e0826d2 100644 --- a/Apps/Sandcastle/gallery/Labels.html +++ b/Apps/Sandcastle/gallery/Labels.html @@ -109,6 +109,18 @@ }); } +function scaleByDistance() { + Sandcastle.declare(scaleByDistance); + + viewer.entities.add({ + position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222), + label : { + text : 'Philadelphia', + scaleByDistance : new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5) + } + }); +} + Sandcastle.addToolbarMenu([{ text : 'Add label', onselect : function() { @@ -139,6 +151,12 @@ fadeByDistance(); Sandcastle.highlight(fadeByDistance); } +}, { + text : 'Scale label by distance', + onselect : function() { + scaleByDistance(); + Sandcastle.highlight(scaleByDistance); + } }]); Sandcastle.reset = function() { diff --git a/CHANGES.md b/CHANGES.md index a149e62bdeaf..603e3b6d475e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,7 @@ Change Log * Fixed exception in 2D in certain cases with polylines when rotating the map. [#4619](https://github.com/AnalyticalGraphicsInc/cesium/issues/4619) * Fixed an issue with constant `VertexArray` attributes not being set correctly. [#4995](https://github.com/AnalyticalGraphicsInc/cesium/pull/4995) * Add support for `Scene.pickPosition` in Columbus view and 2D. [#4990](https://github.com/AnalyticalGraphicsInc/cesium/pull/4990) +* Added `Label.scaleByDistance` to control minimum/maximum label size based on distance from the camera. [#5019](https://github.com/AnalyticalGraphicsInc/cesium/pull/5019) ### 1.30 - 2017-02-01 diff --git a/Source/DataSources/LabelGraphics.js b/Source/DataSources/LabelGraphics.js index 3377176256cf..bb7b8b004444 100644 --- a/Source/DataSources/LabelGraphics.js +++ b/Source/DataSources/LabelGraphics.js @@ -45,6 +45,7 @@ define([ * @param {Property} [options.pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Property specifying the pixel offset. * @param {Property} [options.translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera. * @param {Property} [options.pixelOffsetScaleByDistance] A {@link NearFarScalar} Property used to set pixelOffset based on distance from the camera. + * @param {Property} [options.scaleByDistance] A {@link NearFarScalar} Property used to set scale based on distance from the camera. * @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this label will be displayed. * @@ -87,6 +88,8 @@ define([ this._translucencyByDistanceSubscription = undefined; this._pixelOffsetScaleByDistance = undefined; this._pixelOffsetScaleByDistanceSubscription = undefined; + this._scaleByDistance = undefined; + this._scaleByDistanceSubscription = undefined; this._distanceDisplayCondition = undefined; this._distanceDisplayConditionSubscription = undefined; this._definitionChanged = new Event(); @@ -289,6 +292,18 @@ define([ */ pixelOffsetScaleByDistance : createPropertyDescriptor('pixelOffsetScaleByDistance'), + /** + * Gets or sets near and far scaling properties of a Label based on the label's distance from the camera. + * A label's scale will interpolate between the {@link NearFarScalar#nearValue} and + * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds + * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}. + * Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined, + * scaleByDistance will be disabled. + * @memberof LabelGraphics.prototype + * @type {Property} + */ + scaleByDistance : createPropertyDescriptor('scaleByDistance'), + /** * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this label will be displayed. * @memberof LabelGraphics.prototype @@ -325,6 +340,7 @@ define([ result.pixelOffset = this.pixelOffset; result.translucencyByDistance = this.translucencyByDistance; result.pixelOffsetScaleByDistance = this.pixelOffsetScaleByDistance; + result.scaleByDistance = this.scaleByDistance; result.distanceDisplayCondition = this.distanceDisplayCondition; return result; }; @@ -360,6 +376,7 @@ define([ this.pixelOffset = defaultValue(this.pixelOffset, source.pixelOffset); this.translucencyByDistance = defaultValue(this._translucencyByDistance, source.translucencyByDistance); this.pixelOffsetScaleByDistance = defaultValue(this._pixelOffsetScaleByDistance, source.pixelOffsetScaleByDistance); + this.scaleByDistance = defaultValue(this._scaleByDistance, source.scaleByDistance); this.distanceDisplayCondition = defaultValue(this.distanceDisplayCondition, source.distanceDisplayCondition); }; diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index 019e8527fc77..3ec353a13fc9 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -59,6 +59,7 @@ define([ var pixelOffset = new Cartesian2(); var translucencyByDistance = new NearFarScalar(); var pixelOffsetScaleByDistance = new NearFarScalar(); + var scaleByDistance = new NearFarScalar(); var distanceDisplayCondition = new DistanceDisplayCondition(); function EntityData(entity) { @@ -161,6 +162,7 @@ define([ label.verticalOrigin = Property.getValueOrDefault(labelGraphics._verticalOrigin, time, defaultVerticalOrigin); label.translucencyByDistance = Property.getValueOrUndefined(labelGraphics._translucencyByDistance, time, translucencyByDistance); label.pixelOffsetScaleByDistance = Property.getValueOrUndefined(labelGraphics._pixelOffsetScaleByDistance, time, pixelOffsetScaleByDistance); + label.scaleByDistance = Property.getValueOrUndefined(labelGraphics._scaleByDistance, time, scaleByDistance); label.distanceDisplayCondition = Property.getValueOrUndefined(labelGraphics._distanceDisplayCondition, time, distanceDisplayCondition); } return true; diff --git a/Source/Scene/Label.js b/Source/Scene/Label.js index 67502ac5d74c..3fe84a1b5057 100644 --- a/Source/Scene/Label.js +++ b/Source/Scene/Label.js @@ -75,6 +75,9 @@ define([ if (defined(options.pixelOffsetScaleByDistance) && options.pixelOffsetScaleByDistance.far <= options.pixelOffsetScaleByDistance.near) { throw new DeveloperError('pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.'); } + if (defined(options.scaleByDistance) && options.scaleByDistance.far <= options.scaleByDistance.near) { + throw new DeveloperError('scaleByDistance.far must be greater than scaleByDistance.near.'); + } if (defined(options.distanceDisplayCondition) && options.distanceDisplayCondition.far <= options.distanceDisplayCondition.near) { throw new DeveloperError('distanceDisplayCondition.far must be greater than distanceDisplayCondition.near'); } @@ -99,6 +102,7 @@ define([ this._id = options.id; this._translucencyByDistance = options.translucencyByDistance; this._pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance; + this._scaleByDistance = options.scaleByDistance; this._heightReference = defaultValue(options.heightReference, HeightReference.NONE); this._distanceDisplayCondition = options.distanceDisplayCondition; @@ -613,6 +617,58 @@ define([ } }, + /** + * Gets or sets near and far scaling properties of a Label based on the label's distance from the camera. + * A label's scale will interpolate between the {@link NearFarScalar#nearValue} and + * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds + * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}. + * Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined, + * scaleByDistance will be disabled. + * @memberof Label.prototype + * @type {NearFarScalar} + * + * @example + * // Example 1. + * // Set a label's scaleByDistance to scale by 1.5 when the + * // camera is 1500 meters from the label and disappear as + * // the camera distance approaches 8.0e6 meters. + * label.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0); + * + * @example + * // Example 2. + * // disable scaling by distance + * label.scaleByDistance = undefined; + */ + scaleByDistance : { + get : function() { + return this._scaleByDistance; + }, + set : function(value) { + //>>includeStart('debug', pragmas.debug); + if (defined(value) && value.far <= value.near) { + throw new DeveloperError('far distance must be greater than near distance.'); + } + //>>includeEnd('debug'); + + var scaleByDistance = this._scaleByDistance; + if (!NearFarScalar.equals(scaleByDistance, value)) { + this._scaleByDistance = NearFarScalar.clone(value, scaleByDistance); + + var glyphs = this._glyphs; + for (var i = 0, len = glyphs.length; i < len; i++) { + var glyph = glyphs[i]; + if (defined(glyph.billboard)) { + glyph.billboard.scaleByDistance = value; + } + } + var backgroundBillboard = this._backgroundBillboard; + if (defined(backgroundBillboard)) { + backgroundBillboard.scaleByDistance = value; + } + } + } + }, + /** * Gets and sets the 3D Cartesian offset applied to this label in eye coordinates. Eye coordinates is a left-handed * coordinate system, where x points towards the viewer's right, y points up, and @@ -1066,6 +1122,7 @@ define([ Cartesian3.equals(this._eyeOffset, other._eyeOffset) && NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) && NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance) && + NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) && DistanceDisplayCondition.equals(this._distanceDisplayCondition, other._distanceDisplayCondition) && this._id === other._id; }; diff --git a/Source/Scene/LabelCollection.js b/Source/Scene/LabelCollection.js index 1d4665ef4a32..f68b4c7fdc2c 100644 --- a/Source/Scene/LabelCollection.js +++ b/Source/Scene/LabelCollection.js @@ -171,6 +171,7 @@ define([ backgroundBillboard.id = label._id; backgroundBillboard.translucencyByDistance = label._translucencyByDistance; backgroundBillboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance; + backgroundBillboard.scaleByDistance = label._scaleByDistance; backgroundBillboard.distanceDisplayCondition = label._distanceDisplayCondition; } @@ -263,6 +264,7 @@ define([ billboard.image = id; billboard.translucencyByDistance = label._translucencyByDistance; billboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance; + billboard.scaleByDistance = label._scaleByDistance; billboard.distanceDisplayCondition = label._distanceDisplayCondition; } } diff --git a/Source/Shaders/BillboardCollectionVS.glsl b/Source/Shaders/BillboardCollectionVS.glsl index c56ebd30516c..e9448a6cdf69 100644 --- a/Source/Shaders/BillboardCollectionVS.glsl +++ b/Source/Shaders/BillboardCollectionVS.glsl @@ -2,7 +2,7 @@ attribute vec2 direction; #endif attribute vec4 positionHighAndScale; -attribute vec4 positionLowAndRotation; +attribute vec4 positionLowAndRotation; attribute vec4 compressedAttribute0; // pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates (texture offset) attribute vec4 compressedAttribute1; // aligned axis, translucency by distance, image width attribute vec4 compressedAttribute2; // image height, color, pick color, size in meters, valid aligned axis, 13 bits free @@ -44,7 +44,7 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca halfSize *= ((direction * 2.0) - 1.0); vec2 originTranslate = origin * abs(halfSize); - + #if defined(ROTATION) || defined(ALIGNED_AXIS) if (validAlignedAxis || rotation != 0.0) { @@ -57,7 +57,7 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca tangent = czm_modelViewProjection * tangent; angle += sign(-tangent.x) * acos(tangent.y / length(tangent.xy)); } - + float cosTheta = cos(angle); float sinTheta = sin(angle); mat2 rotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta); @@ -82,22 +82,22 @@ vec4 computePositionWindowCoordinates(vec4 positionEC, vec2 imageSize, float sca { positionWC.xy += halfSize; } - + positionWC.xy += translate; positionWC.xy += (pixelOffset * czm_resolutionScale); - + return positionWC; } -void main() +void main() { // Modifying this shader may also require modifications to Billboard._computeScreenSpacePosition - + // unpack attributes vec3 positionHigh = positionHighAndScale.xyz; vec3 positionLow = positionLowAndRotation.xyz; float scale = positionHighAndScale.w; - + #if defined(ROTATION) || defined(ALIGNED_AXIS) float rotation = positionLowAndRotation.w; #else @@ -105,21 +105,21 @@ void main() #endif float compressed = compressedAttribute0.x; - + vec2 pixelOffset; pixelOffset.x = floor(compressed * SHIFT_RIGHT7); compressed -= pixelOffset.x * SHIFT_LEFT7; pixelOffset.x -= UPPER_BOUND; - + vec2 origin; origin.x = floor(compressed * SHIFT_RIGHT5); compressed -= origin.x * SHIFT_LEFT5; - + origin.y = floor(compressed * SHIFT_RIGHT3); compressed -= origin.y * SHIFT_LEFT3; - + origin -= vec2(1.0); - + float show = floor(compressed * SHIFT_RIGHT2); compressed -= show * SHIFT_LEFT2; @@ -134,30 +134,30 @@ void main() vec2 textureCoordinates = czm_decompressTextureCoordinates(compressedAttribute0.w); #endif - + float temp = compressedAttribute0.y * SHIFT_RIGHT8; pixelOffset.y = -(floor(temp) - UPPER_BOUND); - + vec2 translate; translate.y = (temp - floor(temp)) * SHIFT_LEFT16; - + temp = compressedAttribute0.z * SHIFT_RIGHT8; translate.x = floor(temp) - UPPER_BOUND; - + translate.y += (temp - floor(temp)) * SHIFT_LEFT8; translate.y -= UPPER_BOUND; temp = compressedAttribute1.x * SHIFT_RIGHT8; - + vec2 imageSize = vec2(floor(temp), compressedAttribute2.w); - + #ifdef EYE_DISTANCE_TRANSLUCENCY vec4 translucencyByDistance; translucencyByDistance.x = compressedAttribute1.z; translucencyByDistance.z = compressedAttribute1.w; - + translucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0; - + temp = compressedAttribute1.y * SHIFT_RIGHT8; translucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0; #endif @@ -170,7 +170,7 @@ void main() vec3 alignedAxis = vec3(0.0); bool validAlignedAxis = false; #endif - + #ifdef RENDER_FOR_PICK temp = compressedAttribute2.y; #else @@ -183,11 +183,11 @@ void main() temp = floor(temp) * SHIFT_RIGHT8; color.g = (temp - floor(temp)) * SHIFT_LEFT8; color.r = floor(temp); - + temp = compressedAttribute2.z * SHIFT_RIGHT8; bool sizeInMeters = floor((temp - floor(temp)) * SHIFT_LEFT7) > 0.0; temp = floor(temp) * SHIFT_RIGHT8; - + #ifdef RENDER_FOR_PICK color.a = (temp - floor(temp)) * SHIFT_LEFT8; vec4 pickColor = color / 255.0; @@ -195,15 +195,15 @@ void main() color.a = floor(temp); color /= 255.0; #endif - + /////////////////////////////////////////////////////////////////////////// - + vec4 p = czm_translateRelativeToEye(positionHigh, positionLow); vec4 positionEC = czm_modelViewRelativeToEye * p; positionEC = czm_eyeOffset(positionEC, eyeOffset.xyz); positionEC.xyz *= show; - - /////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// #if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) || defined(DISTANCE_DISPLAY_CONDITION) float lengthSq; @@ -220,7 +220,9 @@ void main() #endif #ifdef EYE_DISTANCE_SCALING - scale *= czm_nearFarScalar(scaleByDistance, lengthSq); + float distanceScale = czm_nearFarScalar(scaleByDistance, lengthSq); + scale *= distanceScale; + translate *= distanceScale; // push vertex behind near plane for clipping if (scale == 0.0) { diff --git a/Specs/DataSources/LabelGraphicsSpec.js b/Specs/DataSources/LabelGraphicsSpec.js index 1575a6057bd2..d210b3035904 100644 --- a/Specs/DataSources/LabelGraphicsSpec.js +++ b/Specs/DataSources/LabelGraphicsSpec.js @@ -39,6 +39,7 @@ defineSuite([ show : true, translucencyByDistance : new NearFarScalar(9, 10, 11, 12), pixelOffsetScaleByDistance : new NearFarScalar(13, 14, 15, 16), + scaleByDistance : new NearFarScalar(17, 18, 19, 20), distanceDisplayCondition : new DistanceDisplayCondition(10.0, 100.0) }; @@ -56,6 +57,7 @@ defineSuite([ expect(label.show).toBeInstanceOf(ConstantProperty); expect(label.translucencyByDistance).toBeInstanceOf(ConstantProperty); expect(label.pixelOffsetScaleByDistance).toBeInstanceOf(ConstantProperty); + expect(label.scaleByDistance).toBeInstanceOf(ConstantProperty); expect(label.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(label.text.getValue()).toEqual(options.text); @@ -71,6 +73,7 @@ defineSuite([ expect(label.show.getValue()).toEqual(options.show); expect(label.translucencyByDistance.getValue()).toEqual(options.translucencyByDistance); expect(label.pixelOffsetScaleByDistance.getValue()).toEqual(options.pixelOffsetScaleByDistance); + expect(label.scaleByDistance.getValue()).toEqual(options.scaleByDistance); expect(label.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); }); @@ -90,6 +93,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.scaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var target = new LabelGraphics(); @@ -109,6 +113,7 @@ defineSuite([ expect(target.show).toBe(source.show); expect(target.translucencyByDistance).toBe(source.translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); + expect(target.scaleByDistance).toBe(source.scaleByDistance); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); @@ -128,6 +133,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.scaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var text = new ConstantProperty('my text'); @@ -144,6 +150,7 @@ defineSuite([ var show = new ConstantProperty(true); var translucencyByDistance = new ConstantProperty(new NearFarScalar()); var pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + var scaleByDistance = new ConstantProperty(new NearFarScalar()); var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var target = new LabelGraphics(); @@ -161,6 +168,7 @@ defineSuite([ target.show = show; target.translucencyByDistance = translucencyByDistance; target.pixelOffsetScaleByDistance = pixelOffsetScaleByDistance; + target.scaleByDistance = scaleByDistance; target.distanceDisplayCondition = distanceDisplayCondition; target.merge(source); @@ -179,6 +187,7 @@ defineSuite([ expect(target.show).toBe(show); expect(target.translucencyByDistance).toBe(translucencyByDistance); expect(target.pixelOffsetScaleByDistance).toBe(pixelOffsetScaleByDistance); + expect(target.scaleByDistance).toBe(scaleByDistance); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); }); @@ -198,6 +207,7 @@ defineSuite([ source.show = new ConstantProperty(false); source.translucencyByDistance = new ConstantProperty(new NearFarScalar()); source.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); + source.scaleByDistance = new ConstantProperty(new NearFarScalar(1.0, 0.0, 3.0e9, 0.0)); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition(10.0, 100.0)); var result = source.clone(); @@ -215,6 +225,7 @@ defineSuite([ expect(result.show).toBe(source.show); expect(result.translucencyByDistance).toBe(source.translucencyByDistance); expect(result.pixelOffsetScaleByDistance).toBe(source.pixelOffsetScaleByDistance); + expect(result.scaleByDistance).toBe(source.scaleByDistance); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); }); diff --git a/Specs/DataSources/LabelVisualizerSpec.js b/Specs/DataSources/LabelVisualizerSpec.js index 55021d652b94..7805b4f18345 100644 --- a/Specs/DataSources/LabelVisualizerSpec.js +++ b/Specs/DataSources/LabelVisualizerSpec.js @@ -154,6 +154,7 @@ defineSuite([ label.show = new ConstantProperty(true); label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); label.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + label.scaleByDistance = new ConstantProperty(new NearFarScalar()); label.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); visualizer.update(time); @@ -179,6 +180,7 @@ defineSuite([ expect(l.show).toEqual(testObject.label.show.getValue(time)); expect(l.translucencyByDistance).toEqual(testObject.label.translucencyByDistance.getValue(time)); expect(l.pixelOffsetScaleByDistance).toEqual(testObject.label.pixelOffsetScaleByDistance.getValue(time)); + expect(l.scaleByDistance).toEqual(testObject.label.scaleByDistance.getValue(time)); expect(l.distanceDisplayCondition).toEqual(testObject.label.distanceDisplayCondition.getValue(time)); testObject.position = new ConstantProperty(new Cartesian3(5678, 1234, 1293434)); @@ -196,6 +198,7 @@ defineSuite([ label.show = new ConstantProperty(true); label.translucencyByDistance = new ConstantProperty(new NearFarScalar()); label.pixelOffsetScaleByDistance = new ConstantProperty(new NearFarScalar()); + label.scaleByDistance = new ConstantProperty(new NearFarScalar()); label.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); visualizer.update(time); @@ -214,6 +217,7 @@ defineSuite([ expect(l.show).toEqual(testObject.label.show.getValue(time)); expect(l.translucencyByDistance).toEqual(testObject.label.translucencyByDistance.getValue(time)); expect(l.pixelOffsetScaleByDistance).toEqual(testObject.label.pixelOffsetScaleByDistance.getValue(time)); + expect(l.scaleByDistance).toEqual(testObject.label.scaleByDistance.getValue(time)); expect(l.distanceDisplayCondition).toEqual(testObject.label.distanceDisplayCondition.getValue(time)); label.show = new ConstantProperty(false); diff --git a/Specs/Scene/LabelCollectionSpec.js b/Specs/Scene/LabelCollectionSpec.js index 694e42eaf079..5b219550580a 100644 --- a/Specs/Scene/LabelCollectionSpec.js +++ b/Specs/Scene/LabelCollectionSpec.js @@ -100,6 +100,7 @@ defineSuite([ expect(label.id).not.toBeDefined(); expect(label.translucencyByDistance).not.toBeDefined(); expect(label.pixelOffsetScaleByDistance).not.toBeDefined(); + expect(label.scaleByDistance).not.toBeDefined(); expect(label.distanceDisplayCondition).not.toBeDefined(); }); @@ -133,6 +134,7 @@ defineSuite([ var backgroundPadding = new Cartesian2(11, 12); var translucency = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var pixelOffsetScale = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); + var scaleByDistance = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var distanceDisplayCondition = new DistanceDisplayCondition(10.0, 100.0); var label = labels.add({ show : show, @@ -154,6 +156,7 @@ defineSuite([ id : 'id', translucencyByDistance : translucency, pixelOffsetScaleByDistance : pixelOffsetScale, + scaleByDistance : scaleByDistance, distanceDisplayCondition : distanceDisplayCondition }); @@ -176,6 +179,7 @@ defineSuite([ expect(label.id).toEqual('id'); expect(label.translucencyByDistance).toEqual(translucency); expect(label.pixelOffsetScaleByDistance).toEqual(pixelOffsetScale); + expect(label.scaleByDistance).toEqual(scaleByDistance); expect(label.distanceDisplayCondition).toEqual(distanceDisplayCondition); }); @@ -617,6 +621,22 @@ defineSuite([ expect(scene).toRender([0, 0, 0, 255]); }); + it('renders label with scaleByDistance', function() { + labels.add({ + position : Cartesian3.ZERO, + text : solidBox, + horizontalOrigin : HorizontalOrigin.CENTER, + verticalOrigin : VerticalOrigin.CENTER, + scaleByDistance: new NearFarScalar(2.0, 1.0, 4.0, 0.0) + }); + + camera.position = new Cartesian3(2.0, 0.0, 0.0); + expect(scene).toRender([255, 255, 255, 255]); + + camera.position = new Cartesian3(4.0, 0.0, 0.0); + expect(scene).toRender([0, 0, 0, 255]); + }); + it('renders label with distanceDisplayCondition', function() { labels.add({ position : Cartesian3.ZERO, @@ -886,6 +906,7 @@ defineSuite([ var scale = 2.0; var translucency = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var pixelOffsetScale = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); + var scaleByDistance = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); label.show = show; label.position = position; @@ -902,6 +923,7 @@ defineSuite([ label.scale = scale; label.translucencyByDistance = translucency; label.pixelOffsetScaleByDistance = pixelOffsetScale; + label.scaleByDistance = scaleByDistance; expect(label.show).toEqual(show); expect(label.position).toEqual(position); @@ -918,6 +940,7 @@ defineSuite([ expect(label.scale).toEqual(scale); expect(label.translucencyByDistance).toEqual(translucency); expect(label.pixelOffsetScaleByDistance).toEqual(pixelOffsetScale); + expect(label.scaleByDistance).toEqual(scaleByDistance); }); it('is destroyed after being removed', function() { @@ -1212,6 +1235,8 @@ defineSuite([ var translucency2 = new NearFarScalar(1.1e4, 1.2, 1.3e6, 4.0); var pixelOffsetScale1 = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); var pixelOffsetScale2 = new NearFarScalar(1.5e4, 1.6, 1.7e6, 8.0); + var scaleByDistance1 = new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0); + var scaleByDistance2 = new NearFarScalar(1.5e4, 1.6, 1.7e6, 8.0); var label = labels.add({ position : position1, @@ -1223,6 +1248,7 @@ defineSuite([ id : id1, translucencyByDistance : translucency1, pixelOffsetScaleByDistance : pixelOffsetScale1, + scaleByDistance : scaleByDistance1, showBackground : true }); @@ -1237,6 +1263,7 @@ defineSuite([ label.id = id2; label.translucencyByDistance = translucency2; label.pixelOffsetScaleByDistance = pixelOffsetScale2; + label.scaleByDistance = scaleByDistance2; scene.renderForSpecs(); @@ -1253,6 +1280,7 @@ defineSuite([ expect(billboard.id).toEqual(label.id); expect(billboard.translucencyByDistance).toEqual(label.translucencyByDistance); expect(billboard.pixelOffsetScaleByDistance).toEqual(label.pixelOffsetScaleByDistance); + expect(billboard.scaleByDistance).toEqual(label.scaleByDistance); expect(billboard.pickPrimitive).toEqual(label); } @@ -1271,6 +1299,7 @@ defineSuite([ id : 'id1', translucencyByDistance : new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0), pixelOffsetScaleByDistance : new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0), + scaleByDistance : new NearFarScalar(1.0e4, 1.0, 1.0e6, 0.0), showBackground : true }); scene.renderForSpecs(); @@ -1392,6 +1421,17 @@ defineSuite([ }); }); + it('scaleByDistance', function() { + var newValue = new NearFarScalar(1.5e4, 1.6, 1.7e6, 8.0); + expect(label.scaleByDistance).not.toEqual(newValue); + label.scaleByDistance = newValue; + scene.renderForSpecs(); + + getGlyphBillboards().forEach(function(billboard) { + expect(billboard.scaleByDistance).toEqual(label.scaleByDistance); + }); + }); + it('translucencyByDistance to undefined', function() { var newValue; expect(label.translucencyByDistance).not.toEqual(newValue); @@ -1414,6 +1454,17 @@ defineSuite([ }); }); + it('scaleByDistance to undefined', function() { + var newValue; + expect(label.scaleByDistance).not.toEqual(newValue); + label.scaleByDistance = newValue; + scene.renderForSpecs(); + + getGlyphBillboards().forEach(function(billboard) { + expect(billboard.scaleByDistance).toEqual(label.scaleByDistance); + }); + }); + it('clusterShow', function() { expect(label.clusterShow).toEqual(true); label.clusterShow = false; @@ -1954,6 +2005,14 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('Label.scaleByDistance throws with nearDistance === farDistance', function() { + var label = labels.add(); + var scaleByDistance = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + label.scaleByDistance = scaleByDistance; + }).toThrowDeveloperError(); + }); + it('new label throws with invalid translucencyByDistance (nearDistance === farDistance)', function() { var translucency = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); expect(function() { @@ -1972,6 +2031,15 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('new label throws with invalid scaleByDistance (nearDistance === farDistance)', function() { + var scaleByDistance = new NearFarScalar(2.0e5, 1.0, 2.0e5, 0.0); + expect(function() { + labels.add({ + scaleByDistance : scaleByDistance + }); + }).toThrowDeveloperError(); + }); + it('Label.translucencyByDistance throws with nearDistance > farDistance', function() { var label = labels.add(); var translucency = new NearFarScalar(1.0e9, 1.0, 1.0e5, 1.0); @@ -1988,6 +2056,14 @@ defineSuite([ }).toThrowDeveloperError(); }); + it('Label.scaleByDistance throws with nearDistance > farDistance', function() { + var label = labels.add(); + var scaleByDistance = new NearFarScalar(1.0e9, 1.0, 1.0e5, 1.0); + expect(function() { + label.scaleByDistance = scaleByDistance; + }).toThrowDeveloperError(); + }); + it('destroys texture atlas when destroying', function() { labels.add({ text : 'a'