1

I am trying to raycast a point on a sphere, and then convert that point to its appropriate latitude and longitude. I came across this question that relates to what I am doing almost exactly on stack exchange

3D coordinates on a sphere to Latitude and Longitude

which uses this function

public static LatLon FromVector3(Vector3 position, float sphereRadius)
    {
        float lat = (float)Math.Acos(position.Y / sphereRadius); //theta
        float lon = (float)Math.Atan(position.X / position.Z); //phi
        return new LatLon(lat, lon);
    }

however, the function is always returning a value somewhere in the range of 0 to 3 for lat and -1 to 1 for longitude.

The program I am using is Unity, does anyone know why I may be getting these incorrect values? I am passing the raycast hit world vector and sphere radius as my parameters and the sphere is centered at world 0,0,0.

Updated Code

public static Vector2 GetLatLonFromVector3 (Vector3 position, float sphereRadius){
        float lat = (float)Mathf.Acos(position.y / sphereRadius); //theta
        float lon = (float)Mathf.Atan2(position.x, position.z); //phi
        lat *= Mathf.Rad2Deg;
        lon *= Mathf.Rad2Deg;
        return new Vector2(lat, lon);
    }

The issue I am now running in to is the values are not being correctly reflected by the quadrant that they are in.

Wenfang Du
  • 8,804
  • 9
  • 59
  • 90
whiskey golf
  • 167
  • 2
  • 14
  • Best to use `Atan2(position.X, position.Z)` in case the Z-component is small. – meowgoesthedog Sep 15 '17 at 21:25
  • When I switch to Atan2 I get completely different values, any idea why? – whiskey golf Sep 15 '17 at 22:05
  • Because `Atan` does not take into account the quadrant in which your "point" [X, Z] is in; also it only covers 180 degrees of angle, not 360 (which is the domain of phi) – meowgoesthedog Sep 15 '17 at 22:10
  • This makes sense and I have switched to Atan2. Any idea how I could rework what I have to account for quadrants? For example, something that should come up as 116 lon is reading as 154. We can do 180-154+90 = 116, so I see the relation, but I am not sure how to account for it for each quadrant. I apologize, math is not my strong suite and appreciate your insights thus far. – whiskey golf Sep 15 '17 at 23:11
  • If you do that explicitly, then you might as well use Atan2, because *that is exactly what Atan2 does* – meowgoesthedog Sep 15 '17 at 23:17
  • I have switched to using Atan2 but I am getting incorrect values. For example, the lat is still reading 90 when I have a point at lat 0. – whiskey golf Sep 15 '17 at 23:18
  • possibly because the X axis points *East* in the convention you use and not North. Also, Atan2 increases in the anticlockwise direction whereas *Bearing* increases in the clockwise. You will need some additional logic to correct this – meowgoesthedog Sep 15 '17 at 23:28
  • Thanks. I will keep poking around and I am sure that I will figure it out. – whiskey golf Sep 15 '17 at 23:32

1 Answers1

5

Acos and atan return values in radians, so from -π (-3.1...) to π (3.1...). In order to convert to degrees, divide by π and multiply by 180. Unity even has a useful constant, Mathf.Rad2Deg to make it easy.

public static LatLon FromVector3(Vector3 position, float sphereRadius)
{
    float lat = (float)Math.Acos(position.Y / sphereRadius); //theta
    float lon = (float)Math.Atan(position.X / position.Z); //phi
    return new LatLon(lat * Mathf.Rad2Deg, lon * Mathf.Rad2Deg);
}
mousetail
  • 7,009
  • 4
  • 25
  • 45