Disabling KML/KMZ clipping into terrain?

Hello,

When a KML/KMZ file containing a label is imported into Cesium, often the label, text, lines, polygons, etc will be clipped into the terrain, which makes them hard to see.

Here’s an example file in Google Earth:

And here’s those entities in Cesium when the file is imported:

The label is stuck under the ground. In some cases, the line is also mostly under the ground.

For some entities, this can be somewhat alleviated by adding <tessellate>1</tessellate> inside the KML file, but for the sake of those using my Cesium application I would rather they do not have to know how to edit the KML file. Plus, tessellate doesn’t work for every KML object.

Is there a way to disable KML/KMZ clipping into terrain, like disableDepthTestDistance? Adding clampToGround to the KML source on import doesn’t work.

I think what you are looking for is setting depthTestAgainstTerrain = false.

For more details, please see the setting’s description here: Globe - Cesium Documentation

@dzung I’d rather not disable depth test against the terrain for the entire globe if possible, just for KML objects that I import.

Additionally, several of the tools in my Cesium application require depthTestAgainstTerrain to be activated.

EDITL @dzung is there any way to disable the depthTestAgainstTerrain for KMLs only?

I’m guessing then that there’s no way to specific to KMLs that they should ignore terrain features via depthTestAgainstTerrain?

Hi there,

There’s plenty of options for you, but it can be a bit more tedious than simply setting one parameter. After the import, you can grab the datasource, and pull out the entities it has created. You can then loop through those items, and adjust them through the API accordingly. I do this, for example, with points (that are converted to billboards) that I now can set clamping individually, or labels which I can set an eyeOffset (0, 0, -100) or something appropriate (often based on the labels height, you might have to pull that out and do some calculations to get it).

In short; no, you can’t set a simple parameter for the KML, but you can loop through the entities it creates and tweak them accordingly.

Cheers,

Alex

@Alexander_Johannesen Is there any way to force billboards and labels to be clamped to terrain? Not just the ellipsoid, but any terrain model that is used afterward.

I tried doing as you said with the billboards and labels’ HeightReference being set to CLAMP_TO_TERRAIN, but this didn’t work for all KMLs - some stayed on top of the terrain, while others would disappear underground and wouldn’t surface at all. Changing eyeOffset didn’t really do anything.

Is is something to do with altitude or height?

No, it kinda depends on what’s in your scene, what sort of terrain you’re trying to clamp to, is it a label or billboard, etc. For example, is it a label, the property you’re after is;

disableDepthTestDistance: Number.POSITIVE_INFINITY

There’s more in this working Sandcastle, so when your entities come through, set the properties that apply. To find out what kind of entities comes through the KML renderer, just dump it to the console and look for any _label, or _billboard, and so on. If they’re non-null, that’s the type;

Cheers,

Alex

1 Like

@Alexander_Johannesen I should say that I was also using the disableDepthTestDistance for both labels and billboards, using the method you described (pulling the entities out of the data source and changing the labels and billboards in each.

The terrain i’m trying to be on top of is an ArcGISTiledElevationTerrainProvider terrain model.

Even with the ellipsoid terrain, however, some KMLs billboards are, for some reason, far beneath the earth on load and slowly ‘rise’ to the surface. When the new terrain is enabled, they rise slightly but only into a flat plane - even with ClampToGround enabled, they stay to some predetermined ‘height’ that I seemingly can’t change, not matching the height of terrain at all. Disabling the new terrain makes them sink back below the earth, so I have to wait a few minutes for it to rise up again.

The options mentioned in the sandcastle are unfortunately not helping in this manner.

Here is what I’m doing:

if (entityCollection) {
  for (let entity of entityCollection) {
    if (entity.billboard) {
      entity.billboard.disableDepthTestDistance = new ConstantProperty(
        Number.POSITIVE_INFINITY
      );
      entity.billboard.heightReference = new ConstantProperty(
        HeightReference.CLAMP_TO_GROUND
      );
    }
    if (entity.label) {
      entity.label.disableDepthTestDistance = new ConstantProperty(
        Number.POSITIVE_INFINITY
      );
      entity.label.heightReference = new ConstantProperty(
        HeightReference.CLAMP_TO_GROUND
      );
      entity.label.verticalOrigin = new ConstantProperty(VerticalOrigin.BASELINE)
    }
    if (entity.polyline) {
      entity.polyline.clampToGround = new ConstantProperty(true);
    }
  }
}

Hmm, it sounds like all the labels height’s are below ground, possibly undefined and just set to 0? Clamping should correct it, but you could also try a crazy thing of setting their height to 4000 or up in the sky, and see if they clamp down. Maybe up-clamping is tricky?

As soon as the KML is rendered, what does a console.log() say about if you took out one of these labels by random?

Cheers,

Alex

1 Like

@Alexander_Johannesen Actually as far as I can tell these are billboards, instead of labels. I’m guessing this because i tested setting label.show = false for every point and still saw the kml points.

Additionally, this isn’t happening for every KML I import - some attach to terrain just fine, and I can’t tell the difference in KML structure or value that allows this to happen.

I also thought that labels don’t have height - only billboards do? And even then, it seems that billboard height is actually a reference to the length of the billboard.

Labels are part of a collection which has 3D Position. Maybe check if these labels are standalone, have a 3D position (so entity.position, not entity.label.position), maybe they have a point or polygon/polyline with it, etc. This is why I asked about that entity’s console.log() output, it might tell you heaps about your issue. If you can replicate it in a Sandcastle, that would truly be the best, inject a sample KML file into it (maybe through Ion) so we can look at it?

Cheers,

Alex

1 Like

It seems to be something to do with number of points, or perhaps computer performance. Having a lot of points in one place and then enabling the new terrain model makes it seem like it doesn’t go to the top of terrain; however, if I reduce the number of points, then it eventually occurs - It just takes a very long time.

I should note, however, that I had to set HeightReference = HeighReference.RELATIVE_TO_GROUND in order to see it.

Is there a way to make sure polylines are clamped too? I tried setting entity.polyline.clampToGround = true, but I ran into this error:

CesiumWidget.js?d9c1:690 An error occurred while rendering.  Rendering has stopped.
DeveloperError: Valid options for arcType are ArcType.GEODESIC and ArcType.RHUMB.
Error
    at new DeveloperError (webpack-internal:///./node_modules/cesium/Source/Core/DeveloperError.js:41:11)
    at new GroundPolylineGeometry (webpack-internal:///./node_modules/cesium/Source/Core/GroundPolylineGeometry.js:113:11)
    at PolylineGeometryUpdater.createFillGeometryInstance (webpack-internal:///./node_modules/cesium/Source/DataSources/PolylineGeometryUpdater.js:441:17)
    at StaticGroundPolylinePerMaterialBatch.add (webpack-internal:///./node_modules/cesium/Source/DataSources/StaticGroundPolylinePerMaterialBatch.js:365:34)
    at insertUpdaterIntoBatch (webpack-internal:///./node_modules/cesium/Source/DataSources/PolylineVisualizer.js:57:45)
    at PolylineVisualizer.update (webpack-internal:///./node_modules/cesium/Source/DataSources/PolylineVisualizer.js:271:5)
    at DataSourceDisplay.update (webpack-internal:///./node_modules/cesium/Source/DataSources/DataSourceDisplay.js:313:31)
    at Viewer._onTick (webpack-internal:///./node_modules/cesium/Source/Widgets/Viewer/Viewer.js:1858:43)
    at Event.raiseEvent (webpack-internal:///./node_modules/cesium/Source/Core/Event.js:141:20)
    at Clock.tick (webpack-internal:///./node_modules/cesium/Source/Core/Clock.js:325:15)

Is this latest Cesium version? Might be a bug with the KML renderer that it doesn’t set ArcType properly?

You could always try to set the ArcType.GEODESIC before turning on clamping, the API might have a bug that it doesn’t. Again, just before you set the clamping, I’d do a console.log(’@@here’, myEntity); and open it and take a screenshot of it and paste it here.

Cheers,

Alex

1 Like

Current version of npm is 1.75 apparently, npm doesn’t want to update it.

It seems that setting ArcType to equal GEODESIC works, and I can clamp to ground afterward.

Here’s an image of an example line before clamping occurs:

It looks like it’s not setting the arcType and clamping is undefined, although there is that known part of the KML import where it doesn’t clamp a line if tesselate isn’t present in the KML.

At least you’re moving forward. :slight_smile: I might try to report that as a bug, ArcType is important for a number of things, and should be set on any polygon/polyline. Do you have anything like a small KML you can share with the bug report as well?

Cheers,

Alex

1 Like

Here’s a KML I can share for the bug report. I created it via Google Earth:
workingKML.kml (1.9 KB)

And here’s the bug report:

1 Like