Coordinates of bounding box of visible map area.

瀏覽次數:3,008 次
跳到第一則未讀訊息

gaurs...@gmail.com

未讀,
2015年3月13日 下午4:11:152015/3/13
收件者:cesiu...@googlegroups.com
Hi,
How do I get the coordinates of the extremes of the visible area of map (the bounding box).
Cesium loads images depending upon the current visible area, so I wanted to ask is there a built in method defined to get the values.

PS. I have attached two images of what I mean by the bounding box(marked with red color).
horizon_covered.png
horizon_visible.png

Hyper Sonic

未讀,
2015年3月14日 下午5:13:182015/3/14
收件者:cesiu...@googlegroups.com
If all four corners show a portion of the Earth you can get a ray for each corner using Camera.prototype.getPickRay then obtain coordinates from the ray to Earth intersects using Globe.prototype.pick (change from Cartesian to Cartographic if you need.)

kirkpatr...@gmail.com

未讀,
2015年4月21日 上午10:41:472015/4/21
收件者:cesiu...@googlegroups.com
I'm in the same boat. For the first instance, you can create a bounding box from upper left to lower right by utilizing the canvas's dimensions:

var posUL = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), Cesium.Ellipsoid.WGS84);
var posLR = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.width, viewer.canvas.height), Cesium.Ellipsoid.WGS84);

You can convert each position to degrees if necessary. This works well, unless any part of the globe's horizon is shown within the viewport, such as your second example. I've yet to figure out how to create a bounding box for that case.

Essentially, I need to know the northern most, southern most, eastern most, and western most points on the globe that are currently visible. I haven't seen any properties/methods in the camera or scene that would help me determine this. Does anyone have any ideas?

Hyper Sonic

未讀,
2015年4月22日 晚上9:15:102015/4/22
收件者:cesiu...@googlegroups.com、kirkpatr...@gmail.com
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;
}

kirkpatr...@gmail.com

未讀,
2015年4月23日 上午9:47:132015/4/23
收件者:cesiu...@googlegroups.com、kirkpatr...@gmail.com
Awesome. I never would have figured that out on my own. Thanks, Hyper Sonic.

Hyper Sonic

未讀,
2015年4月23日 上午11:38:152015/4/23
收件者:cesiu...@googlegroups.com、kirkpatr...@gmail.com
You're welcome. You can modify it to get any number of horizon points. Currently it's every 90 degrees, but it could be modified to say every 10 degrees or whatever. It is an approximation as it assumes a perfect sphere, but it isn't that far off. It doesn't work correctly if the poles are visible since it seeks the north,west,south,east points of the horizon, but it can be modified for any view point.

raghu....@gmail.com

未讀,
2015年10月9日 下午1:35:472015/10/9
收件者:cesium-dev、kirkpatr...@gmail.com
Hi HiperSonic,
As per my requirement i have to show the placemarks with in the bounding box. The solution for the first pic like earth is covering all 4 corners 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 value after tilting/rotating map.

Regards,
Raghu.

Ákos Maróy

未讀,
2016年4月24日 下午3:07:402016/4/24
收件者:cesium-dev、kirkpatr...@gmail.com
Hi,

I wonder if there is a 'combined' result for the above. that would give an estimated area for what the camera is seeing. e.g. see the attached image:



for this, the camera.pickEllipsoid() approach doesn't work, but the horizon calculation approach gives way too large an area, as it will calculate the horizon in all directions, not just the camera viewing direction.


Akos

Gerry Creighton

未讀,
2017年2月2日 上午11:10:502017/2/2
收件者:cesium-dev、kirkpatr...@gmail.com
I'm in the same boat at @kirkparick. I only need a rectangle of what is in view. I used the code example in my project and it draws a much larger rectangle that follows the curvature of the globe.

Gerry Creighton

未讀,
2017年2月2日 下午1:35:022017/2/2
收件者:cesium-dev、kirkpatr...@gmail.com
I actually figured out my issue. Using the code samples in this thread I cobbled together the following for getting a rectangle of the current view.
//view rectangle
    var posUL = cam.pickEllipsoid(new Cesium.Cartesian2(0, 0), Cesium.Ellipsoid.WGS84);
    var posLR = cam.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.width, viewer.canvas.height), Cesium.Ellipsoid.WGS84);
    var posLL = cam.pickEllipsoid(new Cesium.Cartesian2(0, viewer.canvas.height), Cesium.Ellipsoid.WGS84);
    var posUR = cam.pickEllipsoid(new Cesium.Cartesian2(viewer.canvas.width, 0), Cesium.Ellipsoid.WGS84);

//north
    cartographic = ellipsoid.cartesianToCartographic(posUL);
    maxLat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);

   
    //east
    cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater
    cartographic = ellipsoid.cartesianToCartographic(posUR);
    maxLon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);

   
    //south
    cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater
    cartographic = ellipsoid.cartesianToCartographic(posLR);
    minLat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);

   
    //west
    cartesian = rotate(cartesian,rotatee,Math.PI/2); //rotatee now rotater
    cartographic = ellipsoid.cartesianToCartographic(posLL);
    minLon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);

I use minLon, minLat, maxLon and maxLat for other variables in my code but this did the trick.
-Gerry
回覆所有人
回覆作者
轉寄
0 則新訊息