CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.74k stars 3.45k forks source link

KMLDataSource with network links reports BBOX of 0, 0, 0, 0 in 2D #3867

Open hpinkos opened 8 years ago

hpinkos commented 8 years ago

Reported on the forum: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/mIEI2f8drkQ

If you zoom into the map in 2D and look in the Network tab at the xhr calls made, you'll see that around the point you're zoomed so a state fills the screen, the calls made have a bounding box of zero: facilities.kml?BBOX=0,0,0,0. If you zoom back out, the bounding box is correct.

var viewer = new Cesium.Viewer('cesiumContainer', {sceneMode: Cesium.SceneMode.SCENE2D});
var options = {
    camera : viewer.scene.camera,
    canvas : viewer.scene.canvas
};

Sandcastle.addToolbarButton('Load KML Network link',
    function() {
        var kmlText='<kml><NetworkLink>' +
            '<name><![CDATA[Test]]></name>' +
            '<refreshVisibility>0</refreshVisibility>' +
            '<flyToView>0</flyToView>' +
            '<Link><href><![CDATA[../../SampleData/kml/facilities/facilities.kml]]></href>' +
            '<viewRefreshMode>onStop</viewRefreshMode>' +
            '<viewRefreshTime>0</viewRefreshTime>' +
            '<viewFormat>BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]</viewFormat>' +
            '</Link></NetworkLink></kml>';
        var dom = new DOMParser().parseFromString(kmlText, 'text/xml');
        viewer.camera.flyHome(0);
        viewer.dataSources.add(Cesium.KmlDataSource.load(dom, options));
    });
jeffdiederiks commented 8 years ago

I have a partial solution / workaround to this issue. The variable that comes back undefined after loading a datasource is:

viewer.dataSources._dataSources[0]._lastCameraView.bbox

To console.log that variable brings back the corresponding bbox parameters above in degrees rather than radians.

I started with the code in the post above and calculated my own bounding box and parsed my own values into the <viewFormat> tag. Here is my code:

var viewer = new Cesium.Viewer('cesium-container', {
  imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
    url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  }),
  baseLayerPicker : false,
  timeline: false,
  animation: false,
  sceneMode: Cesium.SceneMode.SCENE2D
});

var options = {
  camera : viewer.scene.camera,
  canvas : viewer.scene.canvas
};

viewer.camera.flyHome(0);
viewer.camera.moveEnd.addEventListener(function() {
  var timer = setTimeout(function() {
    var width = viewer.canvas.width;
    var height = viewer.canvas.height;
    var ellipsoid = viewer.scene.globe.ellipsoid;
    var northwestPoint = new Cesium.Cartesian2(0, 0);
    var northwestEllip = viewer.camera.pickEllipsoid(northwestPoint, ellipsoid);
    var southeastPoint = new Cesium.Cartesian2(width, height);
    var southeastEllip = viewer.camera.pickEllipsoid(southeastPoint, ellipsoid);
    var northwestCarto = ellipsoid.cartesianToCartographic(northwestEllip);
    var southeastCarto = ellipsoid.cartesianToCartographic(southeastEllip);
    var westRadians = northwestCarto.longitude;
    var eastRadians = southeastCarto.longitude;
    var northRadians = northwestCarto.latitude;
    var southRadians = southeastCarto.latitude;
    var west = Cesium.Math.toDegrees(westRadians);
    var east = Cesium.Math.toDegrees(eastRadians);
    var north = Cesium.Math.toDegrees(northRadians);
    var south = Cesium.Math.toDegrees(southRadians);
    var kmlText = '<kml>' +
      '<NetworkLink>' +
      '<name><![CDATA[Test]]></name>' +
      '<refreshVisibility>0</refreshVisibility>' +
      '<flyToView>0</flyToView>' +
      '<Link>' +
        '<href><![CDATA[data/facilities.kml]]></href>' +
        '<viewRefreshMode>onStop</viewRefreshMode>' +
        '<viewRefreshTime>0</viewRefreshTime>' +
        '<viewFormat>BBOX=' + west + ',' + south + ',' + east + ',' + north + '</viewFormat>' +
      '</Link>' +
      '</NetworkLink>' +
    '</kml>';
    var kml = new DOMParser().parseFromString(kmlText, 'text/xml');
    viewer.dataSources.add(Cesium.KmlDataSource.load(kml, options));
    var timer2 = setTimeout(function() {
      console.log(viewer.dataSources._dataSources[0]._lastCameraView.bbox);
      console.log("west: " + westRadians + ", south: " + southRadians + ", east: " + eastRadians + ", north: " + northRadians);
    }, 2000);
  }, 500);
});

Two console.log's appear two seconds after the camera is moved. The first console.log outputs the variable mentioned above which is undefined if zoomed in too far on some areas of the map. The second console.log outputs my calculated values.

When zooming in around the Equator is it very hard to get the default bbox parameters to come back undefined. When zooming in near the Prime Meridian I have not been able to get it to break.

new values on zoom

cesium recalculating bounding box

cesium recalculating bounding box-2