Jump to content
  • Advertisement
Sign in to follow this  
homogenized

Movement On Sphere Surface

This topic is 3626 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm having difficulty solving a problem in the project I'm working on and was looking for a little help. I have a sphere (Earth) which I can add surface objects to with a given Latitude/Longitude. I'm adding an airplane object at any given Lat/Long, and want it to move with a constant speed towards a destination Latitude/Longitude. So given Speed, Current Location and Destination, how would I calculate the airplane's new Lat/Long each frame update so that it moves in the right direction at a constant speed? Any help is greatly appreciated.

Share this post


Link to post
Share on other sites
Advertisement
You should store your velocity as a vector with units of degrees/second. The first component represents latitudinal speed, the second longitudinal. Then it breaks down to (hopefully) familiar territory: position2 = position1 + velocity * Δt

Share this post


Link to post
Share on other sites
Quote:
Original post by erissian
You should store your velocity as a vector with units of degrees/second. The first component represents latitudinal speed, the second longitudinal. Then it breaks down to (hopefully) familiar territory: position2 = position1 + velocity * Δt

I almost have this working, but I'm not calculating "a vector with units of degrees/second" properly (my current bad calculation has them flying more slowly around the poles, and quickly at the equator) -- could you go into more detail on how I would calculate this, given that I'm working only with Current & Target Longitude/Latitude and Speed?

My current understanding of this method is that it would work on a flattened map, but on the sphere one degree of Latitude or Longitude can be wildly different distances depending on where you are.

Thank you both for the replies.

Share this post


Link to post
Share on other sites
That's because the lines of longitude are closer at the poles, where lines of latitude are equidistant. You will need to factor in the distance from the axis for that particular component, when changing from angular coordinates to rectilinear position.

Share this post


Link to post
Share on other sites
What I would do:

quick and dirty:
pseudocode
vec3 airplane_pos=position from spherical coords(airplaneLatitude, airplaneLongitude);
vec3 target_pos=position from spherical coords(targetLatitude, targetLongitude);
vec3 delta=(target_pos-airplane_pos)
vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.
airplane_pos+=vel*dt;
airplaneLatitude = latitude from position(airplane_pos)
airplaneLongitude = longitude from position(airplane_pos)


neat and mathy: find dPos/dLatitude and same for longitude, then from dPos/dt=(dPos/dLatitude) * (dLatitude/dt) + (dPos/dLongitude) * (dLongitude/dt) , solve for dLatitude/dt and dLongitude/dt (easy because those 2 dPos vectors are orthogonal), and use those to update latitude and longitude. Could work worse than above "quick and dirty" in practice. If you want I can write derivations for the neat method.

Share this post


Link to post
Share on other sites
Quote:
Original post by Dmytry
pseudocode
vec3 airplane_pos=position from spherical coords(airplaneLatitude, airplaneLongitude);
vec3 target_pos=position from spherical coords(targetLatitude, targetLongitude);
vec3 delta=(target_pos-airplane_pos)
vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.
airplane_pos+=vel*dt;
airplaneLatitude = latitude from position(airplane_pos)
airplaneLongitude = longitude from position(airplane_pos)


Okay, I've been trying to do this for the past day and have made some progress, but am currently stuck.

I'm using this to convert from Lat/Long to spherical coordinates (on my Geographic Position object):

/// <summary>
/// Convert a geographical position to a point on a 3D sphere with given radius.
/// </summary>
public Vector3D ToSphere(Double radius)
{
Double longitudeRad = Longitude * Math.PI / 180d;
Double latitudeRad = Latitude * Math.PI / 180d;

Double y = radius * Math.Sin(latitudeRad);
Double r2 = radius * Math.Cos(latitudeRad);

Double x = r2 * Math.Cos(longitudeRad);
Double z = r2 * Math.Sin(longitudeRad);

return new Vector3D(x, y, z);
}

But I've had trouble finding/creating a method for converting from spherical coordinates back into Longitude/Latitude that I could get to work properly. Could anyone give me a push in the right direction with some pseudo-code?

The only other thing I've had trouble understanding is:
Quote:
vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.

I'm not exactly sure what's being done in this single line, and I'm afraid I'm not converting it correctly to code. Would it be possible to break it down by a step or two? My 3D math is pretty weak, and experience with this type of problem is zero.

I appreciate the responses and patience.

Share this post


Link to post
Share on other sites
Lat/long is spherical polar coordinates. I think what you mean is you lack the transform from Cartesian (XYZ) coordinates to lat/long,

Now, that depends what your XYZ axes are (which one is 'up') but as your spherical->cartesian transforms are:

y = r sin lat
x = r cos lat cos long
z = r cos lat sin long

I can infer that the inverse should be

lat = sin-1 y/r
long = tan-1 z/x

Share this post


Link to post
Share on other sites
That worked perfectly, thank you.

The resulting C# for anyone in the future wanting a method to convert back and forth between Cartesian Coordinates and Longitude / Latitude Spherical Coordinates:

(This assumes a radius of 1. GeoPosition is just an object holding lat/long coordinates.)

static Vector3D ConvertGeoToCart(GeoPosition geoPosition)
{
double longitudeRad = DegreeToRadian(geoPosition.Longitude);
double latitudeRad = DegreeToRadian(geoPosition.Latitude);

double y = Math.Sin(latitudeRad);
double r2 = Math.Cos(latitudeRad);

double x = r2 * Math.Cos(longitudeRad);
double z = r2 * Math.Sin(longitudeRad);

return new Vector3D(x, y, z);
}
static GeoPosition ConvertCartToGeo(Vector3D position)
{
double latitude = Math.Asin(position.Y);
double longitude = Math.Atan2(position.Z , position.X);
return new GeoPosition(RadianToDegree(latitude), RadianToDegree(longitude));
}

static double DegreeToRadian(double degree)
{
return degree * Math.PI / 180.0;
}

static double RadianToDegree(double radian)
{
return radian / Math.PI * 180.0;
}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!