Question

This is specifically a Google Earth API question, but any general geographical solution that can be adapted to it is fine, too.

I'm using the Google Earth API to dynamically put a placemark somewhere on the Earth. Like all placemarks, it has a fixed latitude and longitude. In this case, the altitude is basically always 0. After the placemark is placed, the user may fly the camera around somewhere else and the placemark may not be visible.

What I'd like to be able to do is have a button that would let you automatically look in the direction of the original placemark without changing the camera's position.

In Google Earth API, the user's viewport is represented by a Camera object, which has a latitude and longitude as well as a heading (left-to-right axis) and tilt (up-and-down axis).

So the question can be reduced to: if you have a fixed point on a globe at (lat1, lng1, alt1), how do you calculate the heading and tilt for a camera at (lat1, lng2, alt2) so that it is facing that position?

Était-ce utile?

La solution

Check out the 'bearing' section at this link http://www.movable-type.co.uk/scripts/latlong.html

Here is the javascript he suggests for calculating bearing (or heading).

var y = Math.sin(lng1-lng2) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(lng1-lng2);
var brng = Math.atan2(y, x).toDeg();

Autres conseils

Here's the full, final implementation for turning the current camera of arbitrary altitude towards another lat/lng point of arbitrary altitude. It isn't extremely beautiful (getting the lats and lngs twice because in one I'm using radians and another I'm not) but it works, and causes the Google Earth camera to face whatever it is you want it to face:

//calculate heading/bearing
var lat1 = parseFloat(camera.getLatitude())* Math.PI / 180;
var lng1 = parseFloat(camera.getLongitude())* Math.PI / 180;
var lat2 = parseFloat(target_lat)* Math.PI / 180;
var lng2 = parseFloat(target_lng)* Math.PI / 180;

var dLon = lng2-lng1;
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x).toDeg();

//calculate tilt
lat1 = parseFloat(camera.getLatitude());
lng1 = parseFloat(camera.getLongitude());
lat2 = parseFloat(target_lat);
lng2 = parseFloat(target_lng);
var camera_alt = camera.getAltitude();
var target_alt = your_target_altitude; //meters!

//this uses the distVincenty function and geo.js library here: http://www.movable-type.co.uk/scripts/latlong.html
var distance = parseFloat(distVincenty(Geo.parseDMS(lat1),Geo.parseDMS(lng1),Geo.parseDMS(lat2),Geo.parseDMS(lng2)));
var height_diff = (camera_alt-target_alt);

if(height_diff<0) { //target is above camera, invert equation
    height_diff = (target_alt-camera_alt);
    var tilt = Math.atan(height_diff/distance).toDeg()+90; //the +90 is because of the way Google Earth calculates tilt in such circumstances
} else {
    var tilt = Math.atan(distance/height_diff).toDeg();
}

camera.setTilt(tilt);
camera.setHeading(brng);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top