Reputation: 8833
Given an Entity, I'm trying to figure out if at a particular moment/frame, if one of the entities is viewable on the screen.
The closest I could find was Entity.isVisible, but it seems to just tally the explicit show
properties. It returns true even if...
I also can't find any functions to convert the entity position to viewport coordinates to test if it is at least within the camera view cone.
I had one idea to measure the distance between the entity and the camera kinda like this Cesium.Cartesian3.distance(this.viewer.selectedEntity.position.getValue(Cesium.JulianDate.now()), this.viewer.camera.position);
But obviously the acceptable distance needs to be based on the camera height, FOV and if the camera is even looking in that direction. I haven't yet been able to get the math to work for this solution.
How can I tell if an Entity is currently visible to the user?
Upvotes: 3
Views: 1643
Reputation: 1
Using BoundingSphere and in the frustum culling works for 2D visualizations however will return Cesium.Intersect.INSIDE
for entities that are on the other side of the globe.
A more accurate method would be to use the Occluder class. Not sure why but similar questions across forums and documentation fail to mention this class. Here is a working example given a viewer and a Cartesian3 position:
isPositionInView(position: Cartesian3) {
const globeBoundingSphere = new BoundingSphere(
Cartesian3.ZERO,
this.viewer.scene.globe.ellipsoid.minimumRadius
);
const occluder = new Occluder(
this.globeBoundingSphere,
this.viewer.camera.position
);
return occluder.isPointVisible(position);
}
Note: I use ellipsoid.minimumRadius
here to account for entities that are on the globe's surface.
Upvotes: 0
Reputation: 2827
One of the ways is to use BoundingSphere in the frustum culling. Then check if the bounding sphere of the entity is visible in the culling volume.
const viewer = new Cesium.Viewer('cesiumContainer');
const camera = viewer.camera;
const position = Cesium.Cartesian3.fromDegrees(23.9036, 54.8985);
const frustum = camera.frustum;
const cullingVolume = frustum.computeCullingVolume(
camera.position,
camera.direction,
camera.up
);
const someEntity = viewer.entities.add({
name: 'Some Point',
position: position,
point: {
pixelSize: 14,
color: Cesium.Color.GREEN
}
});
// Bounding sphere of the entity.
let boundingSphere = new Cesium.BoundingSphere();
viewer.dataSourceDisplay.getBoundingSphere(someEntity, false, boundingSphere);
// Check if the entity is visible in the screen.
const intersection = cullingVolume.computeVisibility(boundingSphere);
console.log(intersection);
// 1: Cesium.Intersect.INSIDE
// 0: Cesium.Intersect.INTERSECTING
// -1: Cesium.Intersect.OUTSIDE
I have also made a Cesium Sandcastle example.
Upvotes: 4