label removal problem

Hey all,

I’ve run into this weird bug where I can’t remove labels that I’ve added as primitives. I’ve added a geojson layer for neighborhood boundaries. In order to only display the outlines of the boundaries, I added a highlight outlines function. Then I put my alpha for the layer, itself to zero. Then I add the labels as a primitive so i can remove everything independently if I want to.

So I have three primitives:

  • my layer entity

  • my outline primitives

  • my label primitives

Everything works fine on loading, but in the code to remove all three entities…only the layer and the outlines are removed and the labels remain. Below is my code with the remove code highlighted.

$scope.zillow = function() {

var dataSource = new Cesium.GeoJsonDataSource();

var entities = dataSourceCollection._dataSources;

for (var i = 0; i < entities.length; i++) {

var entity = dataSourceCollection._dataSources[i];

var name = entity._name;

}

                    if (name == 'zillow.geojson') {

                        dataSourceCollection.remove(entity);

                        $scope.czm.scene.primitives.remove(selectOutlinePrimitives);

$scope.czm.scene.primitives.remove(labels);

}

else {

dataSource.loadUrl(’/geoJSON/zillow.geojson’).then(function() {

//Get the array of entities

var entities = dataSource.entities.entities;

Cesium.Math.setRandomNumberSeed(0);

var colorHash = {};

var labels = new Cesium.LabelCollection();

for (var i = 0; i < entities.length; i++) {

//For each entity, create a random color based on the state name.

//Some states have multiple entities, so we store the color in a

//hash so that we use the same color for the entire state.

var entity = dataSource.entities.entities[i];

var laty = entity._properties.centroid_4;

var lony = entity._properties.centroid_5;

var name = entity.name;

var color = colorHash[name];

if (!color) {

color = Cesium.Color.fromRandom({

alpha: 0.0

});

colorHash[name] = color;

}

//Set the polygon material to our random color.

entity.polygon.material = Cesium.ColorMaterialProperty.fromColor(color);

selectHighlight([entity]);

var l = labels.add({

position: Cesium.Cartesian3.fromDegrees(laty, lony, 100),

text: name,

name: ‘neighborhoodlabels’,

font: ‘14px sans-serif’,

fillColor: Cesium.Color.WHITE,

outlineColor: Cesium.Color.BLACK,

style: Cesium.LabelStyle.FILL,

pixelOffset: Cesium.Cartesian2.ZERO,

eyeOffset: Cesium.Cartesian3.ZERO,

horizontalOrigin: Cesium.HorizontalOrigin.CENTER,

verticalOrigin: Cesium.VerticalOrigin.BOTTOM,

translucencyByDistance: new Cesium.NearFarScalar(3000, 1.0, 5000, 0.0),

scale: 1.0

});

}

// Highlight outlines

var geomOlInstances = ;

for (var i = 0; i < entities.length; i++) {

//For each entity, color is by the style rules.

var entity2 = entities[i];

var color2 = Cesium.Color.WHITE;

var gx = new Cesium.PolygonOutlineGeometry.fromPositions({

positions: entity2.polygon._positions._value

});

gx.id = “select_” + entity._id + “ol”;

geomOlInstances.push(new Cesium.GeometryInstance({

geometry: gx,

id: “select_” + entity._id + “ol”,

attributes: {

color: Cesium.ColorGeometryInstanceAttribute.fromColor(color2)

}

})); // outline instances

};

if (selectOutlinePrimitives != undefined &&

$scope.czm.scene.primitives.contains(selectOutlinePrimitives)) {

$scope.czm.scene.primitives.remove(selectOutlinePrimitives);

}

selectOutlinePrimitives = new Cesium.Primitive({

geometryInstances: geomOlInstances,

appearance: new Cesium.PerInstanceColorAppearance({

flat: true,

renderState: {

depthTest: {

enabled: true

},

lineWidth: Math.min(3.05, $scope.czm.scene.maximumAliasedLineWidth)

}

})

});

$scope.czm.scene.primitives.add(selectOutlinePrimitives);

// Add labels

$scope.czm.scene.primitives.add(labels);

$scope.czm.dataSources.add(dataSource);

})};

};

I’ve asked for help on this and I’ve had some suggestions that haven’t worked, either. Here are the suggestions:

It’s hard to say exactly what needs to be done from just the code snippets that you provided; but I think there’s a much easier/better way to go about what you are trying to do.

First, to answer your original question, if you’re trying to remove a label that you’ve created from an entity, then you need to associate that with the entity somehow. The easiest way to do this would add a property to the entity instance, for example you create a label called l in your for loop, you could do “entity.myLabel = l;” and then when you want to remove an entity, you can remove the label to by calling labelCollection.remove(entity.myLabel). This also requires that you store the labelCollection that you created somewhere, and without more context in how your code is structured, I can’t tell you the best way to do that.

However, I mentioned that there was a much easier way and you are doing more work than you need to. You can skip the LabelCollection primitive altogether and just use the existing LabelGraphics class that exists for the purpose of adding a label to an entity. All you need to do is remove all of your existing label code and add these 5 lines inside of the “for (var i = 0; i < entities.length; i++) {“ loop you are using.

        var label = new Cesium.LabelGraphics();

        label.text = new Cesium.ConstantProperty(name);

        label.font = new Cesium.ConstantProperty('14px sans-serif');

        label.verticalOrigin = new Cesium.ConstantProperty(Cesium.VerticalOrigin.BOTTOM);

        entity.label = label;

This will create a label and automatically put it at the entity’s position. When you remove the entity, the label will automatically be removed as well. The LabelGraphics class has all of the same options as the LabelCollection, it’s just meant to be used with Entity instances when working with external data, like GeoJSON.

Let me know if you run into issues or any of that was unclear.

Matt

SUGGESTION 2:

This one should be an easy fix. When working with entity objects, the values are not raw properties but instead are Property objects. This is what allows properties to be specified in a way that changes over time. (SampledProperty, TimeIntervalCollectionProperty, etc…). In your case, you are specific constant values so ConstantProperty is all you need.

Change

label.text = name;

label.font = '14px sans-serif';

label.verticalOrigin = Cesium.VerticalOrigin.CENTER;

To:

label.text = new Cesium.ConstantProperty(name);

label.font = new Cesium.ConstantProperty('14px sans-serif');

label.verticalOrigin = new Cesium.ConstantProperty(Cesium.VerticalOrigin.CENTER);

Hope that helps,

Matt

From looking at your code, I suspect the issue is that the “labels” variable is not in scope when running the remove code. Instead, it’s scoped locally to the function passed to .then().

By the way, for easier debugging of these problems, I recommend using strict mode wherever possible. It will make your code crash when you use an undeclared variable (like in this case), instead of silently using “undefined”

For more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode