1
\$\begingroup\$

I am working on a game where you look at a sphere and get the latitude and longitude of the position.

I get the position on the globe with a raycast along the direction the user is looking. Using this I pass the position and the radius into a method to get the correct latitude and longitude.

Problem

I don't believe my math is correct on this one and I am having some trouble figuring it out.

Code

void Update () {

    if (Physics.Raycast(transform.position, direction: transform.forward, hitInfo: out hit, maxDistance: range))
    {
        Vector3 pointHit = hit.point;
        radius = earth.GetComponent<SphereCollider>().radius;
        //radius = earth.GetComponentInChildren<Renderer>().bounds.extents.magnitude;
        FromVector3(pointHit, radius);
    }
}

public void FromVector3(Vector3 position, float sphereRadius)
{
    float lat = (float)(Math.Acos(position.y / sphereRadius)); 
    float lon = (float)Math.Atan(position.x / position.z); 

    //convert from radians to degrees
    lat *= Mathf.Rad2Deg;
    lon *= Mathf.Rad2Deg;

    Debug.Log(lat + ", " + lon);
}

Output

My Output for latitude ranges from 89 to 90 and doesn't change very much

My Output for longitude ranges from -11 to 11

\$\endgroup\$
2
\$\begingroup\$

I'd modify the method like so:

void Update () {

    if (Physics.Raycast(transform.position, transform.forward, out hit, range))
    {
        // Transform into collider's local coordinate system.
        Vector3 offset = hit.collider.transform.InverseTransformPoint(hit.point);
        longLat = ToSpherical(offset);
    }
}

public Vector2 ToSpherical(Vector3 position)
{
    // Convert to a unit vector so our y coordinate is in the range -1...1.
    position = normalize(position);

    // The vertical coordinate (y) varies as the sine of latitude, not the cosine.
    float lat = Mathf.Asin(position.y) * Mathf.Rad2Deg;

    // Use the 2-argument arctangent, which will correctly handle all four quadrants.
    float lon = Mathf.Atan2(position.x, position.z) * Mathf.Rad2Deg;

    // Here I'm assuming (0, 0, 1) = 0 degrees longitude, and (1, 0, 0) = +90.
    // You can exchange/negate the components to get a different longitude convention.

    Debug.Log(lat + ", " + lon);

    // I usually put longitude first because I associate vector.x with "horizontal."
    return new Vector2(lon, lat);
}
\$\endgroup\$
13
  • \$\begingroup\$ Are the latitude and longitude not dependent on the radius of the sphere at all? \$\endgroup\$
    – Dtb49
    Oct 3 '17 at 16:41
  • \$\begingroup\$ We took radius out of the equation by normalizing our offset vector. ;) \$\endgroup\$
    – DMGregory
    Oct 3 '17 at 16:42
  • \$\begingroup\$ Ahh I see, it's been a while since I used Trig. So it wouldn't affect anything if the size of the sphere changed? \$\endgroup\$
    – Dtb49
    Oct 3 '17 at 16:53
  • \$\begingroup\$ If you find it hard to believe, try working through an example on paper to prove it. Doubling the radius of the sphere will double the length of the pointHit offset vector we pass to the spherical coordinate method. But then normalizing the vector completely erases that doubling (or whatever other scale factor we choose to apply) \$\endgroup\$
    – DMGregory
    Oct 3 '17 at 17:09
  • 1
    \$\begingroup\$ Edited to show how to deal with this. You'll want to also subtract the collider's center point if it might be off-center in its object's local coordinate system. \$\endgroup\$
    – DMGregory
    Oct 4 '17 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.