How to get the extent of the current camera position

Is there any way to get the extent of the current camera view? Also, is there any good way to subscribe to an event to know when this changes?

There is no existing code to get the extent for the current camera view. I can post some code for you, but it would only work for top down views. Is that OK?

Currently, there are no events when the camera is changed, but that may be added in the future. You could check to see if it changed in the render loop.

I'm not sure if it would be helpful or not, but I'll take any help you're willing to offer. What I'm trying to write some code that would make a call to a WFS server and I need to be able to pass it the bounding box for what data I want back. I'm guessing this would be somewhat similar to how it's done for WMS, but I'm not positive.

Is there an update on this? I need to do something similar. I'm trying to fetch an export map function from an ArcGIS mapservice, and need a bounding box.

Here's some code I use that does a "pretty good" job of solving this problem. This is borrowed heavily from this forum post: http://cesium.agi.com/forum.html?place=msg%2Fcesium-dev%2FjYlLEnyv7lM%2FwUKX0EKUqQQJ.

    var c2 = new Cesium.Cartesian2(0, 0);
    var leftTop = scene.getCamera().controller.pickEllipsoid(c2, ellipsoid);
    c2 = new Cesium.Cartesian2(scene.getCanvas().width, scene.getCanvas().height);
    var rightDown = scene.getCamera().controller.pickEllipsoid(c2, ellipsoid);

    if (leftTop != null && rightDown != null) { //ignore jslint
        leftTop = ellipsoid.cartesianToCartographic(leftTop);
        rightDown = ellipsoid.cartesianToCartographic(rightDown);
        return new Cesium.Extent(leftTop.longitude, rightDown.latitude, rightDown.longitude, leftTop.latitude);
    } else {
        //The sky is visible in 3D
        return null;
    }

As the code comment mentions this does not work if the sky is in view and it may not work for other situations as well so use at your own risk and make sure to test heavily before using in production.

Hi All,

As per my requirement i have to show the placemarks with in the bounding box. The solution for the given by you for earth covering all 4 corners(sky is not in view) is working fine.. but when i tilting or rotating the map in same area where i can see all placemarks i could not get the correct bounding box values as i could see only few placemarks there. Does it need to do something with rotate/tilt angle..?

Could you please help me to get bounding box values after tilting/rotating map.

Thanks,
Raghu.

If the map is not North-Up, you’ll have to get the coordinates of all four corners, so also leftBottom and rightTop.
You can then use Rectangle.fromCartographicArray() to have Cesium sort out the box that contains the map area.

This box will be North-Up, so it will cover a larger area than what you have on screen. Whether that is a problem depends on your use-case.

Thanks Willem..

I tried earlier calculating coordinates of four corners but not used Rectangle.fromCartographicArray(). Now i could see them and also observed getting some other placemarks data also as you said it covers larger area.

Could you please suggest me any work around for getting bbox when sky is in view/visible..?

Regards,
Raghu.

Hi Raghu,

Sorry, I have no idea how to handle the case when the sky is visible. Not something trivial I’m afraid.

I actually wrote some code a while back to do this. It uses the Bresenham algorithm to walk the pixels from upper-left to center, and lower-right to center. It does a pickEllipsoid() at each screen pixel location, and if it finds a valid pixel on both the UL line and LR line, uses those to do screen -> Cartesian -> Cartographic -> Rectangle conversion.

Thanks Mark Erikson… for suggesting Bresenham algorithm. I used the answer posted here http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript to get the corners of map even sky is in view… hope i am getting right values…Thanks…

Willem / Mark Erikson, as you said rectangle covering a little bit large area what we have in screen… so can we have any solution to overcome this problem… like subtracting any offset value from the coordinates…?

Thanks,

Raghu.

Hi Raghu,

I’m also working on to get the camera position (Top left, Top right, Bottom left, Bottom right) on the screen. I’m able to get the position when the sky is not on the scene. If the sky is visible it fails to get the position.

Can you please share the code to handle this using Bresenham Algorithm (as mentioned in the above comment). I’ve tried the code, but I’, getting error while initializing the new Coordinates. e.g. new Coordinates(0,0) => Error: Uncaught ReferenceError: Coordinates is not defined.

Appreciate your support.

Thanks,

Prem.

Hi Prem,

I used the following code to traverse from canvas corners. For example calculating leftTop, traversing from lefttop to rightdown, i have given findCoordinate(new Cesium.Cartesian2(0,0), new Cesium.Cartesian2(canvasWidth, canvasHeight)), same way you can calculate other corners by providing appropraite values. Hope it helps you.

function (startCoordinates, endCoordinates) {

var coordinate = scene.camera.pickEllipsoid(startCoordinates, this.ellipsoid);

// Translate coordinates

var x1 = startCoordinates.x;

var y1 = startCoordinates.y;

var x2 = endCoordinates.x;

var y2 = endCoordinates.y;

// Define differences and error check

var dx = Math.abs(x2 - x1);

var dy = Math.abs(y2 - y1);

var sx = (x1 < x2) ? 1 : -1;

var sy = (y1 < y2) ? 1 : -1;

var err = dx - dy;

coordinate = scene.camera.pickEllipsoid({x:x1, y:y1}, this.ellipsoid);

if(coordinate) {

return coordinate;

}

// Main loop

while (!((x1 == x2) && (y1 == y2))) {

 var e2 = err << 1;

 if (e2 > -dy) {

   err -= dy;

   x1 += sx;

 }

 if (e2 < dx) {

   err += dx;

   y1 += sy;

 }

 coordinate = scene.camera.pickEllipsoid({x:x1, y:y1}, this.ellipsoid);

if(coordinate) {

return coordinate;

}

}

return;

},

Thanks,

Raghu.

Hello Raghu,

Thank you for sharing the code.