Here’s a SandCastle that can determine the horizon bounding box. I’ve borrowed the labeling code from the picking SandCastle demo. Rotate logic from Google Earth API math3d.js . The frustum can bind it even further, but this might help for cases where the horizon binds before the frustum does. If you had one of these total surround displays https://www.youtube.com/watch?v=a2e9noEg1zg frustums wouldn’t even exist! Frustums are for the Solid Angle deficient http://en.wikipedia.org/wiki/Solid_angle .

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var CC3=Cesium.Cartesian3;

var camera = viewer.scene.camera;

var ellipsoid = viewer.scene.globe.ellipsoid;

var rad = 6371000; //Earth average radius

var entityN = viewer.entities.add({

label : {

show : false

}

});

var entityW = viewer.entities.add({

label : {

show : false

}

});

var entityS = viewer.entities.add({

label : {

show : false

}

});

var entityE = viewer.entities.add({

label : {

show : false

}

});

Sandcastle.addToolbarButton(‘horizon points’, function() {

//horizon basics

var dist=CC3.magnitude(camera.position);

var angle=Math.asin(rad/dist);

var toSurf=Math.sqrt(Math.pow(dist,2)-Math.pow(rad,2));

//‘horizon arm’

var rotatee = camera.position.clone();

rotatee = CC3.negate(rotatee,new CC3());

CC3.normalize(rotatee,rotatee);

var rotater = new CC3(0,0,1);

CC3.cross(rotatee,rotater,rotater);

var rotated = new CC3();var cartesian = new CC3();

rotated = rotate(rotatee,rotater,angle);

cartesian = scaleVector(toSurf,rotated);

CC3.add(cartesian,camera.position,cartesian);

//north

dropOne(entityN,cartesian);

//east

cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater

dropOne(entityE,cartesian);

//south

cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater

dropOne(entityS,cartesian);

//west

cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater

dropOne(entityW,cartesian);

});

function dropOne(entity,cartesian)

{

if (cartesian) {

var cartographic = ellipsoid.cartesianToCartographic(cartesian);

var longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);

var latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);

entity.position = cartesian;

entity.label.show = true;

entity.label.text = ‘(’ + longitudeString + ', ’ + latitudeString + ‘)’;

} else {

entity.label.show = false;

}

}

function rotate(rotatee,rotater,angle)

{

//rotater: unit vector, angle:radians

//CCW looking from vector tip to vector base

var CC3=Cesium.Cartesian3;var rotated=new CC3();

var c = Math.cos(angle);var s = Math.sin(angle);

var dotScale = CC3.dot(rotatee,rotater,new CC3());

var rotaterScaled = scaleVector(dotScale,rotater);

var vPerpAxis = CC3.subtract(rotatee,rotaterScaled,new CC3()); //using Pythagoras theorem

var comp1 = scaleVector(c,vPerpAxis);

var vPerpPerpAxis = CC3.cross(rotater,vPerpAxis,new CC3()); //perp to both of these

var comp2 = scaleVector(s,vPerpPerpAxis);

return addVectors([rotaterScaled,comp1,comp2]);

}

function scaleVector(scale,vector)

{

var temp = new Cesium.Cartesian3();

temp.x=scale*vector.x;temp.y=scale*vector.y;temp.z=scale*vector.z;

return temp;

}

function addVectors(vectors)

{

var resultant=new Cesium.Cartesian3(0,0,0);

var i=0;while(i<vectors.length)

{

resultant.x+=vectors[i].x;

resultant.y+=vectors[i].y;

resultant.z+=vectors[i].z;

i+=1;

}

return resultant;

}

``