Search Unity

Coordinate Systems

Discussion in 'Scripting' started by lakedoo23, Apr 21, 2018.

  1. lakedoo23

    lakedoo23

    Joined:
    Nov 5, 2014
    Posts:
    8
    What would be the best approach in a script to translate real-world coordinates (lat, long) to a scene in Unity? I am taking real-world GPS (lat, long) coordinates in a 60km area and want to translate/map it to a terrain with size 6000x6000, the center of the terrain (3000, 0, 3000) is where I want to be the point of origin.

    Currently, I am using Haversine Formula to get the distance and bearing between the lat/long of the center point and to the lat/long of the other object(s) and try to scale the distance down so I can calculate the position of the other object in the scene. But I have a feeling there might be a better way to do this.
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I place 2 objects in the game world and assign them lat/long values. I then use those to convert any value between the two coordinate systems.
     
  3. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Here's the code I wrote for it. I can't claim it is the most efficient or anything, but it has been working for me. I haven't tested the antimeridian parts of the code in game yet.

    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class LatLon {
    6.     //class that converts latitude / longitude to Unity position and the reverse
    7.     //Got the formula from here
    8.     //https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
    9.  
    10.     //convert a coordinate from one set of ranges to another set of ranges
    11.     private static float convertCoordinate(float oldValue, float oldMin, float oldMax, float newMin, float newMax)
    12.     {
    13.         float oldRange = oldMax - oldMin;
    14.         float newRange = newMax - newMin;
    15.         float returnValue = (((oldValue - oldMin) * newRange) / oldRange) + newMin;
    16.         return returnValue;
    17.     }
    18.  
    19.     //A LatLon Vector2 includes Latitude as the x value and Longitude as the y value
    20.     //A Unity world coordinate has x as the west/east (longitude) and z as the north/sounth (latitude)
    21.  
    22.     //This method takes a LatLon Vector2 and translates it into this zone's game world coordinates
    23.     //It does this by taking two points, a Noth West point and South East point in both LatLon and Unity world space positions to do the translation
    24.     public static Vector3 GetUnityPosition(Vector2 latLonPosition, Vector2 northWestLatLon, Vector2 southEastLatLon, Vector3 northWestUnity, Vector3 southEastUnity)
    25.     {
    26.         //check if this zone covers the antimeridian (where 180 and -180 degress longitude meet)
    27.         if (southEastLatLon.y < northWestLatLon.y)
    28.         {
    29.             //Add 360 to any negative longitude positions so that longitude values are lower the further west
    30.             southEastLatLon = new Vector2(southEastLatLon.x, southEastLatLon.y + 360f);
    31.             if (latLonPosition.y < 0f)
    32.             {
    33.                 latLonPosition = new Vector2(latLonPosition.x, latLonPosition.y + 360f);
    34.             }
    35.         }
    36.         float newUnityLat = convertCoordinate(latLonPosition.x, southEastLatLon.x, northWestLatLon.x, southEastUnity.z, northWestUnity.z);
    37.         float newUnityLon = convertCoordinate(latLonPosition.y, southEastLatLon.y, northWestLatLon.y, southEastUnity.x, northWestUnity.x);
    38.         Vector3 unityWorldPosition = new Vector3(newUnityLon, 200f, newUnityLat);
    39.         return unityWorldPosition;
    40.     }
    41.  
    42.     public static Vector2 GetLatLonPosition(Vector3 unityPosition, Vector2 northWestLatLon, Vector2 southEastLatLon, Vector3 northWestUnity, Vector3 southEastUnity)
    43.     {
    44.         bool antimeridian = false;
    45.         //check if this zone covers the antimeridian (where 180 and -180 degress longitude meet)
    46.         if (southEastLatLon.y < northWestLatLon.y)
    47.         {
    48.             antimeridian = true;
    49.             //Add 360 to any negative longitude positions so that longitude values are lower the further west
    50.             southEastLatLon = new Vector2(southEastLatLon.x, southEastLatLon.y + 360f);
    51.         }
    52.         float newlat = convertCoordinate(unityPosition.z, southEastUnity.z, northWestUnity.z, southEastLatLon.x, northWestLatLon.x);
    53.         float newlon = convertCoordinate(unityPosition.x, southEastUnity.x, northWestUnity.x, southEastLatLon.y, northWestLatLon.y);
    54.         if (antimeridian)
    55.         {
    56.             if (newlon > 180f)
    57.             {
    58.                 newlon = newlon - 360f;
    59.             }
    60.         }
    61.         Vector2 latLonPosition = new Vector2(newlat, newlon);
    62.         return latLonPosition;
    63.     }
    64. }

    This is all I place on the two objects in the scene. One of them is in the north west, and the other is in the south east. The vector2 is Latitude X, Longitude Y.
    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class LocationMarker : MonoBehaviour {
    5.  
    6.     public Vector2 LatLon;
    7.      // Use this for initialization
    8.     void Start () {
    9.  
    10.      }
    11.  
    12.      // Update is called once per frame
    13.      void Update () {
    14.  
    15.      }
    16. }
    Example usage from my own game. Might not make sense out of context, but the scripts have too much unrelated stuff to post here in full. These are from two different scripts. I have no idea why I named the vector2 the same as the other class, I didn't notice until now. That was by mistake.
    Code (csharp):
    1.  
    2.                 ShipObject.transform.position = LatLon.GetUnityPosition(currentLatLong, northWestLocationObject.GetComponent<LocationMarker>().LatLon, southEastLocationObject.GetComponent<LocationMarker>().LatLon, northWestLocationObject.transform.position, southEastLocationObject.transform.position);
    3.  
    Code (csharp):
    1.  
    2.     //updates the current latitude and longitude
    3.     public void UpdateLatLong()
    4.     {
    5.         currentLatLong = LatLon.GetLatLonPosition(gameObject.transform.position, northWestLocation.GetComponent<LocationMarker>().LatLon, southEastLocation.GetComponent<LocationMarker>().LatLon, northWestLocation.transform.position, southEastLocation.transform.position);
    6.     }
    7.  
     
    Last edited: Apr 21, 2018
    junhossi likes this.
  4. lakedoo23

    lakedoo23

    Joined:
    Nov 5, 2014
    Posts:
    8
    Awesome! Thank you for the advice and code, I will try it soon.
     
  5. lakedoo23

    lakedoo23

    Joined:
    Nov 5, 2014
    Posts:
    8
    Thanks, @Joe-Censored, this solution worked really well for me!
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Glad to hear that :)

    By the way, on line 38 where I include a Y value of 200f is something specific to my game. Its a sailboat game and the ocean surface is always at Y value of 200f. So you'll probably want to do something with that.
     
    Last edited: Apr 25, 2018
  7. Misnomer

    Misnomer

    Joined:
    Jul 15, 2013
    Posts:
    28
    @Joe-Censored thanks a lot for your suggestion! I've been trying to draw a map in correct scale for 2 days, trying all kinds of formulas and your solution finally worked.
     
    Joe-Censored likes this.
  8. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I forgot I posted this, but I'm glad it helped.
     
  9. sandeep135

    sandeep135

    Joined:
    Sep 13, 2022
    Posts:
    2
    How to get Noth West point and South East point from longitude and latitute points?
     
  10. sandeep135

    sandeep135

    Joined:
    Sep 13, 2022
    Posts:
    2