# How to rotate a point on the surface of a ellipsoid?

say i have a Point at 0,0,0, it has a x, y, z radius which make a capsule, i have a object above it who’s distance to the point is it’s y radius, and i have a Vector2 angle (the z axis is useless for rotating around it)

say for example the angle was 90, 0. the object should be to the left of the point with the distance being the x radius,or if the angle was 0, 90 the object should be infront of the point with the distance being the z radius

how would i implement this? sorry for my drawing skills

From what I understand, it’s not a capsule but an ellipsoid.

You can work in the spherical coordinate system, see the formula in the wikipedia page.
`θ` and `φ` are your `x` and `y` angle, `r` is your `z` but a constant in your case
`a`, `b`, and `c` are defined by your vertical and horizontal radius (I assume horizontal radius is used twice).

1 Like

i dont get it, there are too many formula’s to see, can you show me the important ones plz

this was the best i could come up with

only problem is that rotating it on the y axis is very weird, it depends on the X rotation and is really weird

Ignore the Pos variable i forgot to remove it from a previous attempt!

OP’s drawing looks like an ellipsoid.

The Unity Capsule primitive (both the CapsuleCollider and the Mesh) is definitely a cylinder connecting two hemispheres.

Those are not the same shapes.

As for OP’s question, the concept of rotating anything on any surface is to first find the normal at the point you are standing on.

Raycasts can give you normals, given back in the RaycastHit object when you hit the object.

This normal vector would be used to produce a rotation using one of the axis-relevant factory helpers in the Quaternion class, or perhaps just good old Transform.LookAt() with the second argument.

i want a pure mathematical solution, this wont work, my ellipsoid is fictional and doesnt exist, only the x, y,z radius and center of it

For a sphere, the haversine formulas might be what you need (Haversine formula - Wikipedia), for an ellipsoid (=earth) it is regrettably significantly more complicated (Vincenty's formulae - Wikipedia). Not quite sure if this is what you need; here an implementation to get from a given start Latitude+Longitude to an end Lat+Lon on an elipsoid, using heading angle + distance.

``````/// <summary> Solves direct geodetic problem according to vincenty equation</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool VincentyDirect(double2 startLatLonRad, double fwdAzimuthRad, double distance_m, int iteration_limit, out double2 endLatLonRad, out double rev_azimuthRad, out int iterations)
{
double epsilon = 0.0000001f;
math.sincos(fwdAzimuthRad, out double sin_alpha_1, out double cos_alpha_1);
double tan_u_1 = (1.0 - WGS84.f) * math.tan(startLatLonRad.x);
double cos_u_1 = 1.0 / math.sqrt(1.0 + tan_u_1 * tan_u_1);
double sin_u_1 = tan_u_1 * cos_u_1;

double sigma_1 = math.atan2(tan_u_1, cos_alpha_1);
double sin_alpha = cos_u_1 * sin_alpha_1;
double cos_sq_alpha = 1.0 - sin_alpha * sin_alpha;
var asq = WGS84.a * WGS84.a;
var bsq = WGS84.b * WGS84.b;
double u_sq = cos_sq_alpha * (asq - bsq) / (bsq);
double a_ = 1.0 + u_sq / 16384.0 * (4096.0 + u_sq * (-768.0 + u_sq * (320.0 - 175.0 * u_sq)));
double b_ = u_sq / 1024.0 * (256.0 + u_sq * (-128.0 + u_sq * (74.0 - 47.0 * u_sq)));

double cos_2_sigma_m;
double sin_sigma;
double cos_sigma;
double delta_sigma;

double sigma = distance_m / (WGS84.b * a_);
double sigma_;
iterations = 0;

do
{
cos_2_sigma_m = math.cos(2.0 * sigma_1 + sigma);
math.sincos(sigma, out sin_sigma, out cos_sigma);

delta_sigma = b_ * sin_sigma * (cos_2_sigma_m + b_ / 4.0 * (cos_sigma * (-1.0 + 2.0 * cos_2_sigma_m * cos_2_sigma_m) -
b_ / 6.0 * cos_2_sigma_m * (-3.0 + 4.0 * sin_sigma * sin_sigma) * (-3.0 + 4.0 * cos_2_sigma_m * cos_2_sigma_m)));

sigma_ = sigma;
sigma = distance_m / (WGS84.b * a_) + delta_sigma;

iterations++;
} while ((math.abs(sigma - sigma_) > epsilon) && (iterations < iteration_limit));

double x = sin_u_1 * sin_sigma - cos_u_1 * cos_sigma * cos_alpha_1;
endLatLonRad.x = math.atan2(sin_u_1 * cos_sigma + cos_u_1 * sin_sigma * cos_alpha_1, (1.0 - WGS84.f) * math.sqrt(sin_alpha * sin_alpha + x * x));

double lambda = math.atan2(sin_sigma * sin_alpha_1, cos_u_1 * cos_sigma - sin_u_1 * sin_sigma * cos_alpha_1);
double c_ = WGS84.f / 16.0 * cos_sq_alpha * (4.0 + WGS84.f * (4.0 - 3.0 * cos_sq_alpha));

double l_ = lambda - (1.0 - c_) * WGS84.f * sin_alpha * (sigma + c_ * sin_sigma * (cos_2_sigma_m + c_ * cos_sigma * (-1.0 + 2.0 * cos_2_sigma_m * cos_2_sigma_m)));

rev_azimuthRad = math.atan2(sin_alpha, -x);

return (iterations < iteration_limit);
}
``````

And you might need these two formulas to convert a Lat+Lon + height representation of a position on an ellipsoid to 3D:

``````        /// <summary> From geodetic coordinates to ECEF (geocentric) in a right handed coordinate system</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double3 LatLonRadToEllipsoidRightHanded(double2 LatLonPoint, double elevation = 0)
{
LonLatToGeoCentric(LatLonPoint.x, out double rad_xy, out double z, elevation);
math.sincos(LatLonPoint.y, out double sinLon, out double cosLon);
double3 result;
result.x = rad_xy * cosLon;
result.y = rad_xy * sinLon;
result.z = z;
return result;
}
/// <summary> Low level conversion from geodetic to geocentric (ECFS) coordinates </summary>
static void LonLatToGeoCentric(double latRad, out double rad_xy, out double z, double elevation)
{
math.sincos(latRad, out double sinLat, out double cosLat);

/* radius of curvature of the ellipsoid */
var Rc = WGS84.a / math.sqrt(1 - WGS84.e2 * sinLat * sinLat);

/* radius on the equator plane */
rad_xy = (Rc + elevation) * cosLat;

//z coordinate
z = (Rc * (1 - WGS84.e2) + elevation) * sinLat;
}
``````