Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KML viewer.flyTo placemark goes underground #4327

Open
hpinkos opened this issue Sep 16, 2016 · 13 comments
Open

KML viewer.flyTo placemark goes underground #4327

hpinkos opened this issue Sep 16, 2016 · 13 comments

Comments

@hpinkos
Copy link
Contributor

hpinkos commented Sep 16, 2016

Reported on the forum: https://groups.google.com/forum/?hl=en#!topic/cesium-dev/E27D7WJHWZ8
Using viewer.flyTo for a pin created by this KML file results in the camera going under ground.

var viewer = new Cesium.Viewer('cesiumContainer'); 
var options = { 
    camera : viewer.scene.camera, 
    canvas : viewer.scene.canvas,
    clampToGround: true
}; 
var zoomTarget; 

var kmlFile = "https://raw.githubusercontent.com/googlemaps/kml-samples/gh-pages/kml/Placemark/placemark.kml"; 
var promise = Cesium.KmlDataSource.load(kmlFile, options); 
Cesium.when(promise, function(dataSource) { 
    viewer.dataSources.add(dataSource); 
    zoomTarget = dataSource.entities.values[0]; 
}); 

Sandcastle.addToolbarButton('Fly to Placemark', function() { 
    viewer.flyTo(promise); 
}, 'toolbar'); 

Interestingly enough, the same thing does not happen when you create a pin at the same location with the entities API

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

var pinBuilder = new Cesium.PinBuilder(); 
var entity = viewer.entities.add({ 
    position : Cesium.Cartesian3.fromDegrees(-122.087461,37.422069), 
    label : { 
        text : 'pin', 
        verticalOrigin : Cesium.VerticalOrigin.TOP 
    }, 
    billboard : { 
        image : pinBuilder.fromColor(Cesium.Color.SALMON, 24).toDataURL(), 
        verticalOrigin : Cesium.VerticalOrigin.BOTTOM, 
    } 
}); 

Sandcastle.addToolbarButton('Fly To Entity', function() { 
    viewer.flyTo(entity); 
}, 'toolbar'); 
@hpinkos
Copy link
Contributor Author

hpinkos commented Sep 16, 2016

"The difference between the two examples appears to be the initial bounding sphere computed for the entity. For the second example, the center of the bounding sphere is identical to the entity's position. Not so with the KML example -- the z-component in particular is much smaller. After the second button click, the bounding sphere gets recalculated and the center becomes roughly the same. "

@hpinkos
Copy link
Contributor Author

hpinkos commented Oct 20, 2016

This was fixed sometime between 1.26 and 1.27, but I'm not exactly sure by what

@hpinkos hpinkos closed this as completed Oct 20, 2016
@mramato mramato reopened this Oct 20, 2016
@mramato
Copy link
Contributor

mramato commented Oct 20, 2016

The only reason this appeared fix was because the clampToGround setting in KmlDataSource is now properly added, I updated the original code sample to properly trigger the bug again.

@hpinkos
Copy link
Contributor Author

hpinkos commented Oct 20, 2016

var viewer = new Cesium.Viewer('cesiumContainer'); 
var options = { 
    camera : viewer.scene.camera, 
    canvas : viewer.scene.canvas,
    clampToGround: true
}; 
var zoomTarget; 
var kml = '<?xml version="1.0" encoding="utf-8"?>\
<kml xmlns="http://www.opengis.net/kml/2.2">\
  <Placemark>\
    <name>My office</name>\
    <description>This is the location of my office.</description>\
    <Point>\
      <coordinates>-122.52087481,37.422069</coordinates>\
    </Point>\
  </Placemark>\
</kml>';
var parser = new DOMParser();
var promise = Cesium.KmlDataSource.load(parser.parseFromString(kml, "text/xml"), options); 
Cesium.when(promise, function(dataSource) { 
    viewer.dataSources.add(dataSource); 
    zoomTarget = dataSource.entities.values[0]; 
}); 

Sandcastle.addToolbarButton('Fly to Placemark', function() { 
    viewer.flyTo(promise); 
}, 'toolbar'); 

@hpinkos
Copy link
Contributor Author

hpinkos commented Mar 24, 2017

@ggetz
Copy link
Contributor

ggetz commented Aug 25, 2017

@mramato
Copy link
Contributor

mramato commented Aug 8, 2018

To fix this, I think we just need to update BillboardVisualizer.getBoundingSphere to sample terrain (if available) rather than relying on _clampedPosition (which is only using the highest level loaded instead of the highest available). I think we can get the terrainProvider from the EntityCluster, but haven't looked that closely.

@mramato
Copy link
Contributor

mramato commented Aug 8, 2018

Will also need to update other visualizers with clamping behavior.

@ainthek
Copy link

ainthek commented Mar 22, 2020

The original sample with KML is still not working.
a) So do you have any real code fix to fix this code ?
b) what a user of https://cesium.com/cesiumjs/cesium-viewer/index.html? can do to fix this ?
c) shell the users fix the KML ? how ?
It is very unclear from all this cross communication. thanx for help.

It is important to instruct users of viewers app
`var viewer = new Cesium.Viewer('cesiumContainer');
var options = {
camera : viewer.scene.camera,
canvas : viewer.scene.canvas,
//elipsoid:Cesium.Ellipsoid.WGS84,
clampToGround: false
};

viewer.extend(Cesium.viewerCesiumInspectorMixin);

var zoomTarget;

var kmlFile = "https://raw.githubusercontent.com/ainthek/map-projects/master/data/samples/BMXRaceTracks.googleearthpro.kml.gdal.gpx.gdal.kml";
var promise = Cesium.KmlDataSource.load(kmlFile, options);
Cesium.when(promise, function(dataSource) {
viewer.dataSources.add(dataSource);
zoomTarget = dataSource.entities.values[0];
});
viewer.flyTo(promise);`

@OmarShehata
Copy link
Contributor

@ainthek I can still reproduce the bug. Until there's a fix, one workaround is to initiate a second flyTo after the first one, which seems to always go to the right location:

viewer.flyTo(promise).then(() => viewer.flyTo(promise)); 

Sandcastle. Obviously not ideal to go underground in the first place though.

@ainthek
Copy link

ainthek commented Mar 25, 2020

@OmarShehata thanx for workaround, but WHY is this magic hack
not part of the default Cesium Viewer app ? So when I publish link
https://cesium.com/cesiumjs/cesium-viewer/index.html?src=..... my friends can actuale see something ? ;-0)))))

@OmarShehata
Copy link
Contributor

@ainthek I replied in your forum thread here about ways you can solve this for your particular use case.

@ncutt010
Copy link

ncutt010 commented Oct 13, 2021

Here's a workaround that worked for me

Get the camera height after flyTo is complete. When the camera height is a negative number is when we run into the bug. If that's the case, simply run the flyTo method again until the height is a positive number

function flyToCustom (entity, attempt = 0) {
    let hpr = new HeadingPitchRange(CesiumMath.toRadians(0), CesiumMath.toRadians(-90.0), 0)
    viewer.flyTo(entity, {duration: 1.0, offset: hpr}).then(() => {
        const ellipsoid = viewer.scene.globe.ellipsoid
        const height = ellipsoid.cartesianToCartographic(viewer.scene.camera.position).height
        if (height < 0 && attempt < 50) { // only attempt 50 times before giving up
          flyToCustom(entity, attempt + 1)
        }
      }
    })
}

Also, increasing the altitude of the HeadingPitchRange seemed to mitigate the problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants