Scene.globe.pick delivers undefined

Hi,

is there a trick - for the usage of scene.globe.pick . I want to determine the intersection with the terrain, but scene.globe.pick delivers in most cases undefined - see Sandcastle.

Disclaimer: Iâ€™m not deeply familiar with CesiumJS or picking, but will try to give some hints, involving a rough guess about what you are trying to achieve:

You apparently want to compute the intersection of the rays with a theoretical ground level. The important point here is: You donâ€™t want to compute an â€śactualâ€ť intersection with geometry (otherwise youâ€™d have to use a Terrain Provider somewhere).

It this is true, then the main issues are:

1. The rays are horizontal, at z=0, so â€¦ theyâ€™ll hardly intersect anything. This can easily be fixed by letting the rays start at a z-value that is greater than 0, and letting them end at a z-value that is smaller than 0.

2. The intersection checks are performed â€śtoo earlyâ€ť, when the relevant part of the globe is not yet rendered. This can be fixed by not using `globe.pick`, but computing the intersection point analytically.

Specifically: The `globe.pick` function computes the intersection with something that has been rendered. But calling the function directly in the sandcastle will cause this to happen when the globe is not rendered yet.

But instead of using `globe.pick`, you can compute the intersection of the ray with the WGS84 ellipsoid that approximates the surface of the earth (and for which the theoretical, approximated ground level is at z=0).

An updated sandcastle - the changes marked with `UPDATED`:

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

// MĂĽnchen
// UPDATED: Start the ray at height "200", which is "above the ground"
var starting_point = Cesium.Cartesian3.fromDegrees(	11.54985, 48.13041, 200);

// Bavaria
// UPDATED: End the ray at height "-100", which is "below the ground"
var end = Cesium.Cartesian3.fromDegrees(11.54582, 48.13072, -100);

viewer.camera.flyTo({
destination : starting_point,
complete: analysisVisible
});

var lat = 48.13041;
for (var i=0; i<100; i++)
{
lat = lat + 0.00001;
// UPDATED: Start the ray at height "200", which is "above the ground"
starting_point = Cesium.Cartesian3.fromDegrees(11.54985, lat, 200);
analysisVisible();
}

// * View analysis
function analysisVisible() {

// * Calculate the direction of the ray
let direction = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.subtract(
end,
starting_point,
new Cesium.Cartesian3()
),
new Cesium.Cartesian3()
);
// Establish a ray
let ray = new Cesium.Ray(starting_point, direction);

//let result = viewer.scene.globe.pick(ray, viewer.scene); // calculate intersection points

// UPDATED: Compute the intersection of the ray with
// the surface of the WGS84 ellipsoid that approximates
// the shape of the earth
let intersectionInterval = Cesium.IntersectionTests.rayEllipsoid(ray, Cesium.Ellipsoid.WGS84);
if (Cesium.defined(intersectionInterval)) {
console.log("Result - ok");

// Compute the intersection point from the interval
var t = intersectionInterval.start > 0.0 ? intersectionInterval.start : intersectionInterval.stop;
var result = Cesium.Ray.getPoint(ray, t, new Cesium.Cartesian3());

drawLine(result,  starting_point, Cesium.Color.GREEN); // visual
drawLine(result,  end, Cesium.Color.RED); // is not visible
} else {
console.log("Result - undefined");
drawLine(starting_point,  end, Cesium.Color.YELLOW); // UPDATED: indicate error
}
}

// * draw line
function drawLine(starting_point,  end, color) {
polyline: {
positions: [starting_point,  end],
width: 5,
material: color,
depthFailMaterial: color,
//clampToGround: true // UPDATED: I found that confusing :-)
}
});
}
``````

It should show the expected rays, starting above da TherĂ¤sienwiesn, and ending under da Bavaria:

1 Like

Hi,

@Marco13 thank you for the explanation.

I also found out, that I have to check if the terrain is loaded, if I wat to use the terrain.

Regards

RĂĽdiger

Indeed, if you actually want to compute intersections with the terrain, then things may become more tricky. The `globe.pick` function can then only be used when the respective part of the terrain is actually visible on the screen.

(One can argue that this is implied by the word â€śpickingâ€ť, which suggests that this is related to some user interaction on the screen, with the rendered model. There are also mechanisms for performing similar checks for the geometry when it is not rendered, but Iâ€™d have to look into the details here, and at some point, these details (i.e. the most sensible solution) might depend on your exact goalsâ€¦)

1 Like