Flying to camera.lookAt (Migrating from Google Earth Plugin API lookAt)

Hello,

Created this stack overflow question. I will re-paste the question here. Sorry in advance if that’s not ok with the forum. On a tight deadline and am pulling my hair out over getting this right.

Thanks to all the contributors for your help!

http://stackoverflow.com/questions/41104269/cesium-js-flying-to-camera-lookat-migrating-from-google-earth-plugin-api-lookat

up vote
down votefavorite

Needing some help migrating my flying functionality from the Google Earth plugin to Cesium. Basically in ge I create a lookAt and called setAbstractView like below

var ge = google.earth.createInstance('map3d')
var lookAt = TVV.mapObject.createLookAt('');
lookAt.set(
    21.2765107698755,
    -157.825362273258,
    0,
    ge.ALTITUDE_RELATIVE_TO_GROUND,
    20.1690873648706,
    74.9605580474674,
    764.534479411941
);
ge.getView().setAbstractView(lookAt);

That was my code for google earth plugin. In cesium following the migration guides I do:

// fly to code that works with cesium (but a little bit off)
viewer.camera.flyTo({
    destination : Cesium.Cartesian3.fromDegrees(-157.825362273258, 21.2765107698755, 764.534479411941),
    orientation : {
        heading : Cesium.Math.toRadians(20.1690873648706),
        pitch : Cesium.Math.toRadians(74.9605580474674 - 90.0),
        roll: 0
    }
})

That code goes to almost the right place. I have to drag it down over to the right to see my placemark that I previously set (so the view is not exactly what it was in Google earth).

So I tried this code I also found.

// code that works with cesium
var center = Cesium.Cartesian3.fromDegrees(-157.825362273258, 21.2765107698755);
var heading = Cesium.Math.toRadians(20.1690873648706);
var pitch = Cesium.Math.toRadians(74.9605580474674);
var range = 764.534479411941;
viwer.camera.lookAt(center, new Cesium.HeadingPitchRange(heading, pitch, range));

That code looks MUCH closer to the previous google earth plugin view. However, of course, it does not fly the camera to the view. It only sets the view right away.

My question is, how can I fly the camera to the lookAt view in cesium, taking advantage of my lat, lng, heading, pitch, and range values?

Here are the relevant API docs from GE and Cesium should you find them useful.

GE createLookAthttps://developers.google.com/earth/documentation/reference/interface_g_e_plugin.html#a82f1b3618531a6bfab793b04c76a43e7

GE Camera Control (search for “Panning to an absolute location”)https://developers.google.com/earth/documentation/camera_control

Cesium lookAt https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#lookAt

Cesium flyTo https://cesiumjs.org/Cesium/Build/Documentation/Camera.html#flyTo

I also found this but was unsure about how to integrate it. If anybody could provide a codepen/jsfiddle or something of the like that would be greatly appreciatedhttps://groups.google.com/forum/#!topic/cesium-dev/r5rddMUeS80

Hello,

This is the perfect place to ask a question like this. We do check stack overflow, but not as frequently as we check the forum here.

You might be able to use viewer.flyTo to accomplish what you want to do. You are trying to fly to an entity, right?

Here is an example of flying to a pin:

var viewer = new Cesium.Viewer(‘cesiumContainer’, {timeline : false, animation : false});

var pinBuilder = new Cesium.PinBuilder();

var bluePin = viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.170726, 39.9208667),
billboard : {
image : pinBuilder.fromColor(Cesium.Color.ROYALBLUE, 48).toDataURL(),
verticalOrigin : Cesium.VerticalOrigin.BOTTOM
}
});

viewer.flyTo(bluePin, {
offset: new Cesium.HeadingPitchRange(0, -Cesium.Math.PI_OVER_TWO, 3000)
});

``

Best,

Hannah

Hannah,

That code is awesome! Does just what I wanted.

For everbody else’s reference. I just used the converted values from the Google Earth Plugin I had before for my HeadingPitchRange so I did…

var heading = Cesium.Math.toRadians(20.1690873648706g);
var pitch = Cesium.Math.toRadians(74.9605580474674 - 90);
var range = 764.534479411941;

TVV.mapObject.flyTo(entity, {
offset: new Cesium.HeadingPitchRange(heading, pitch, range)
});

``

Hi,

As the editor for Cesium’s development team, I’m always looking for good apps to showcase on our website: http://cesiumjs.org/demos.html

Is the project you’re working on in a position to be showcased? If so, I can send you our guidelines. Typically, we need a few paragraphs describing the project and how it uses Cesium, as well as some screenshots. Let me know if this is something you would like to do.

Regards,

Sarah

Hey Hannah,

Have a small follow up question. If I run the code above to fly to an entity with an offset and then drag around, change the pitch, etc with the mouse, what is the best way to figure out what the new offset is, such that I could get heading, pitch, range, lat/lng and save them perhaps in a cookie or elsewhere and reload the page to the same new view? Basically how can I modify the original coordinates after I move around and save them?

Thanks!

Ben

Hi Ben,

I’m a little confused about what your question is, but it sounds like you would like to save and load camera views. Is that correct?

You can see an example for how to do this in this post: https://groups.google.com/d/msg/cesium-dev/lolHXdDitOg/GC4iPNiICgAJ

Best,

Hannah

Thanks Hannah yeah I know about this. I guess I’m going to have to modify the way I’m doing things a bit. Here’s the issue.

I have locations and views for those locations. So each location has a lat/lng. It then has five or so views, which show different pitches/headings/ranges basically giving a tour around the placemark.

So the above code was awesome because it flew to the different locations with offset values given by the views lat/lng/heading/pitch/range.

Currently I store those values above in degrees (because all my data original came from GE). So for one view I have

lat

lng

heading

tilt (which is subtract 90 from before converting to radians for Cesium)

range

For a location I have

lat

lng

So I create the location placemark/entity and fly to it with an offset for the view. It works great. However, in my admin I have an interface to be able to CHANGE a view. This is where it gets tricky.

So the user drags and rotates the camera in the admin page to adjust the way the view looks, to show the back of a model (where the entity is over) for example instead of the front. So the camera has changed,

placemark has stayed the same.

Now I need to save the state of this view to be able to do the same thing and fly to the entity with the offset next time and produce the same result as their modified view. Does that make sense? I need to have the user with their mouse change the original view coords and then grab them to save programatically so I can use the same fly to entity call with modified offset data I had before.

lat

lng

heading

tilt (which is subtract 90 from before converting to radians for Cesium)

range

Really appreciate your help. Thanks Hannah

Ah okay.
Well lat and lng should be the lat and lng of the entity, correct? So you can get that from

var cartographicRadians = viewer.scene.globe.ellipsoid.cartesianToCartographic(entity.position.getValue(viewer.clock.currentTime));

var lat = Cesium.Math.toDegrees(cartographicRadians.latitude);

var lng = Cesium.Math.toDegrees(cartographicRadians.longitude);

Though it sounds like these values won’t change, just the heading/tilt/range will.

Heading and pitch can be retrieved by camera.heading and heading.pitch

For range, you’ll want to subtract the entity position from the camera position and get the magnitude:

var vector = Cesium.Cartesian3.subtract(entity.position.getValue(viewer.clock.currentTime), viewer.scene.camera.positionWC, new Cesium.Cartesian3());

var range = Cesium.Cartesian3.magnitude(vector);

Does this help? If I’m still missing something let me know.

Best,

Hannah