Points/Labels stuck under terrain?

I’ve been trying to create new entities for a project i’m working on - that being a point with a label attached to it. I’m creating the point using a function that takes in a cartesian (from a user clicking on the map) and uses that to put the point/label down.

However, when I do this, regardless of whatever setting heightReference is, the point - and its corresponding label - is hidden underneath the terrain:

Zooming in causes it to be further hidden underneath the terrain until barely anything is visible.

How can I stop this from happening? Even if I don’t have any heightReference property, this still happens.

Hey there,

Always good to show us your code, but here’s a short version;

{
position: myCartesian,
point: { … },
label: {
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
}
}

Show us some code, and it’ll be easier to help you forward. There’s several other ways of offsetting the label, like pixelOffset and eyeOffset, but depends on your needs.

Cheers,

Alex

@Alexander_Johannesen Unfortunately, using verticalOrigin didn’t stop this from happening.

My code looks like:

export function createEntity(worldPosition) {
    let entToCheck = viewer.entities.getById('entToPlace')

    if (typeof entToCheck !== 'undefined' && entToCheck) {
        viewer.entities.removeById('entToPlace')
    }

    viewer.entities.add({
        name: 'Entity Location',
        id:'entToPlace',
        position : worldPosition,
        point : {
            color : Color.WHITE,
            pixelSize : 10,
            heightReference : HeightReference.RELATIVE_TO_GROUND,
            scaleByDistance: new NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
        },
        label: {
            text: "Entity Location",
            font: "20px sans-serif",
            showBackground: true,
            horizontalOrigin: HorizontalOrigin.CENTER,
            pixelOffset: new Cartesian2(0.0, 10.0),
            pixelOffsetScaleByDistance: new NearFarScalar(
              1.5e2,
              3.0,
              1.5e7,
              0.5
            ),
        },
    });

    viewer.scene.requestRender();

}

Hey,

So, do you get any reference errors or anything? You’re using HeightReference.* directly, instead of Cesium.HeightReference.*. If I use;

point : {
            color : Cesium.Color.WHITE,
            pixelSize : 10,
            heightReference : Cesium.HeightReference.RELATIVE_TO_GROUND,
            scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
        },
        label: {
            text: "Entity Location",
            font: "20px sans-serif",
            showBackground: true,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            pixelOffset: new Cesium.Cartesian2(0.0, -10.0),
            pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
              1.5e2,
              3.0,
              1.5e7,
              0.5
            ),
        },

It works fine. I also changed your pixelOffset to use a negative number in the Y axis to push it above ground (pixelOffset: new Cesium.Cartesian2(0.0, -10.0)). See if this helps. I’ve added a complete example underneath as well which you can copy and paste into a sandcastle to play with.

Cheers,

Alex

var viewer = new Cesium.Viewer("cesiumContainer");

var point = viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
    point : {
            color : Cesium.Color.WHITE,
            pixelSize : 10,
            heightReference : Cesium.HeightReference.RELATIVE_TO_GROUND,
            scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
        },
        label: {
            text: "Entity Location",
            font: "20px sans-serif",
            showBackground: true,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            pixelOffset: new Cesium.Cartesian2(0.0, -10.0),
            pixelOffsetScaleByDistance: new Cesium.NearFarScalar(
              1.5e2,
              3.0,
              1.5e7,
              0.5
            ),
        },
  });

viewer.flyTo(point);

@Alexander_Johannesen
Earlier in the document i’m using:

import {
    Cartesian2,
    Cartesian3,
    Color,
    HeightReference,
    HorizontalOrigin,
    NearFarScalar,
} from 'cesium'

So there are no reference errors.

The label is now above the point but I still have it partially under terrain:

If I place the point when zoomed out, then zoom in, it will be subsumed by the terrain entirely. If I zoom all the way in and place the point, it will be more visible (label will be above terrain, but point won’t be) until I zoom out again at which point it becomes hidden under the terrain.

Could this be due to how we’re getting Cartesian values? For you, you’re defining as Cartesian3.fromDegrees(-75.59777, 40.03883), whereas I’m using an imported Cartesian value. Could this cause the point that i’m using to have a Z value that’s under the terrain or perhaps not perpendicular to its surface or something?

Hiya,

Yup, it sounds like your cartesian point is under the terrain model / ellipsoid globe, although your picture does look a bit odd, usually the ellipsoid clipping isn’t that dramatic. There are ways to clamp things to the terrain / globe you can play with, different from what kind of entity you’re playing with (points, lines, polygons, billboard, etc.) Polygons can do clampToGround:true, for example, not sure about points (it’s a bit hard to find out what entities support what feature, you’ll have to go through the docos)

How do you do it now? scene.pickPosition() or something similar? Are you using a terrain model, or just the globe ellipsoid? Do height references need to be accurate? You can always add a few cms to the height to push it above ground, Cesium can be a bit sensitive to it.

The other, wilder option is to play with globe transparency to see if your points are indeed being pushed under;

viewer.scene.globe.translucency.enabled = true;
viewer.scene.globe.translucency.frontFaceAlphaByDistance = new Cesium.NearFarScalar(
   100.0, 0.0,
   10000.0, 1.0
);

Cheers,

Alex

@Alexander_Johannesen

I’m using a screenspace handler to get the mouse click, and indeed scene.pickPosition(event.position) to obtain a cartesian upon a mouse click.

For the Earth, i’m using EllipsoidTerrainProvider({}).

How can I add height to the point after getting the cartesian?

Hey,

By some hokery-pokery. :slight_smile: First convert the Cartesian to a Cartographic, then pull height (in meters), add the amount (ie. +0.2), and convert back to Cartesian and update the position. It’s tedious, I don’t know if there’s a simple way to do it, maybe some of the Cesium guys can pipe in here.

I use our own framework which is a bunch of wrappers around the coordinates that does this automatically, but if you search for Cesium Cartesian.toCartographic() and Cartesian.fromDegrees() (with added radian conversion) you should be able to do it.

Cheers,

Alex

1 Like

@Alexander_Johannesen
I gave this a try and it did improve it slightly, but for some reason it can still get stuck under the terrain, especially if I pick the point when I am zoomed from very far away. It looks like doing it from a far distance puts the Z coord somehere under the terrain (which has a lower res model until I zoom in…)

Making the globe transluscent also apparently had the effect of making any points placed down go straight through to the other side of the Earth. In any case, the points were always under the surface.

I feel like there has to be another way to do this…what were the other suggestions you had?

Hi,

Just to look into clamping. There’s a number of entities that support it, not sure about point, but if you switch to billboards I seem to recall they do.

Cheers,

Alex

@Alexander_Johannesen
I’m really not sure what i’m doing wrong here - i implemented billboards using an image I created myself, an ‘X’:

x

(the image is white)

But even with following the sandcastle about Billboards, it is still buried under the terrain:

image

Is there some other kind of setting that I’m missing or something wrong with my terrain provider?

Hey,

How do you create your entities? Here’s the two main properties;

heightReference : Cesium.HeightReference.CLAMP_TO_GROUND,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM

Cheers,

Alex

Hello,

I’m creating via this:

viewer.entities.add({
        name: 'Marker of Entity Location',
        id:'marker',
        position : worldPosition,
        billboard : {
            color : Color.WHITE,
            image: "/resources/images/x.png",
            imageSubRegion: new BoundingRectangle(27, 103, 22, 22),
            heightReference : HeightReference.CLAMP_TO_GROUND,
            verticalOrigin: VerticalOrigin.BOTTOM,
            scaleByDistance: new NearFarScalar(1.5e2, 2.0, 1.5e7, 0.5),
        },
        label: {
            text: "Entity Location",
            font: "20px sans-serif",
            showBackground: true,
            horizontalOrigin: HorizontalOrigin.CENTER,
            pixelOffset: new Cartesian2(0.0, -10.0),
            pixelOffsetScaleByDistance: new NearFarScalar(
            1.5e2,
            3.0,
            1.5e7,
            0.5
            ),
        },
    });

Removing the label doesn’t do anything to make the billboard more visible.

So, are you sure your image is actually loaded? Remove the scalineByDistance and imageSubRegion, and load an image you know is visible first. Kill the label for now, just try to see a billboard of sorts first. I’m also slightly skeptical of your image starting with a slash, for some root directory, not sure where that’s going to? I’d usually use ‘…/resources/…’ depending on where your code is run from and where your directory sits.

Cheers,

Alex

Hello,

Should have mentioned before, but removing the imageSubRegion before made it work, but it was huge and it still could be buried under terrain.

image

What’s interesting to note is that in 2D side view, it can be placed and stands fine:

But going back to globe view, it gets buried:

Yup, that’s the globe clipping. Now play with eyeOffset and pixelOffset (especially the z axis) to move it to and fro. Apart from that, I think some of the Cesium guys need to chip in from here.

Cheers,

Alex

1 Like

Getting rid of imageSubRegion: new BoundingRectangle(27, 103, 22, 22), made it appear; using eyeOffset: new Cartesian3(0.0, 0.0, -10.0), made it appear more readily. It’s still getting stuck a bit into the terrain, but it’s visible:

image

Interestingly, the eyeOffset’s value determines how close one can get to the Earth before it disappears completely…if it’s -10, you can get 10 metres away before it disappears; if it’s -100, you can get 100 metres away before it disappears; etc. That’s not related to the terrain, but rather the camera’s distance to the object in question.

EDIT:

You can completely prevent it from clipping by using disableDepthTestDistance, which I’ve set to the diameter of the Earth (after which it begins to clip)

image

image

For those looking, my entity creation looks like:

viewer.entities.add({
            name: 'Marker of Entity Location',
            id:'marker',
            position : worldPosition,
            billboard : {
                color : Color.RED.withAlpha(0.7),
                image: "/resources/images/x.png",
                scale: 0.2,
                eyeOffset: new Cartesian3(0.0, 0.0, -10.0),
                heightReference: HeightReference.CLAMP_TO_GROUND,
                verticalOrigin: VerticalOrigin.CENTER,
                horizontalOrigin: HorizontalOrigin.CENTER,
                disableDepthTestDistance: 1.2742018*10**7 // Diameter of Earth
            },
            label: {
                text: "Entity Location",
                font: "20px sans-serif",
                showBackground: true,
                eyeOffset: new Cartesian3(0.0, 0.0, -10.0),
                horizontalOrigin: HorizontalOrigin.CENTER,
                pixelOffset: new Cartesian2(0.0, -20.0),
                pixelOffsetScaleByDistance: new NearFarScalar(
                1.5e2,
                3.0,
                1.5e7,
                0.5
                ),
                disableDepthTestDistance: 1.2742018*10**7
            },
        });

Thank you for all the help!

Thanks for sharing your issue.

We ended up with a similar solution, but the -10 eye offset recommendation does help alleviate it some. Thanks for that Alex!

The downside here is that if you have terrain loaded…you will see this “through” the mountain or over the horizon right?. It will appear to be in front of the mountain if your camera is close to the ground.
But that is probably not a issue for a lot of use cases.

Here is a sandcastle I made to demo the issue:
Sandcastle Demo