在增强现实应用程序中向用户显示最近的 POI 时出现问题

问题描述 投票:0回答:0

我正在 Unity 中开发一个增强现实应用程序,它可以不断获取用户的当前位置并找到离他最近的兴趣点。我使用 Firestore 数据库存储所有兴趣点的名称和地理坐标(纬度、经度)。我在这里附上了两个脚本:

UserLocation.cs
:它定期获取用户的当前位置并调用一个函数,
FinalFunc()
来自另一个脚本,
CompareCoordinates.cs
首先从数据库中检索有关兴趣点的数据,然后调用另一个函数,
GetClosestCoord()
计算所有 45 个 POI 与用户当前位置的距离,并返回最近的 POI 的详细信息(纬度、经度和名称)。所有这一切都发生在每次
Update()
通话中。

    public class UserLocation : MonoBehaviour
    {
    float latitude;
    float longitude;

    int flag = 1;

    void Update()
    {
        GetUserLocation();
        CompareCoordinates.instance.FinalFunc(latitude, longitude);
    }

    void GetUserLocation()
    {
        if (!Input.location.isEnabledByUser) // CHECKING FOR PERMISSION, IF "true" IT MEANS USER GAVE PERMISSION FOR USING LOCATION INFORMATION
            Permission.RequestUserPermission(Permission.FineLocation);
        StartCoroutine(GetLatLonUsingGPS());
    }

    IEnumerator GetLatLonUsingGPS()
    {
        Input.location.Start(5, 5);
        
        // flag variable used to run this block only once 
        if(flag==1)
        {
            int maxWait = 1;
            while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
            {
                yield return new WaitForSeconds(1);
                maxWait--;
            }
            flag--;
        }
                     

        // Access granted and location value could be retrieved
        longitude = Input.location.lastData.longitude;
        latitude = Input.location.lastData.latitude;
    }
   }

    public class CompareCoordinates : MonoBehaviour
    {
    public Text lat;
    public Text lon;
    public Text placeName;
    public GameObject obj;

    int flag = 1;

    public static CompareCoordinates instance;

    List<object> placeLatitude = new List<object>();
    List<object> placeLongitude = new List<object>();
    List<object> nameOfPlace = new List<object>();
    List<float> finalCoord;
    List<float> finalCoord2;

    float close = 99999f;
    float final;
    float finalLat;
    float finalLon;
    string place;

    FirebaseScript firebaseObj;


    void Start()
    {
        instance = this;

        firebaseObj = obj.GetComponent<FirebaseScript>();
    }

    // Retrieves data from Firestore database
    public void GetData()
    {
        firebaseObj.db.Collection("Points of Interest").Document("Places").GetSnapshotAsync().ContinueWith(task =>
        {
            DocumentSnapshot snapshot = task.Result;
            if (snapshot.Exists)
            {
                Dictionary<string, object>  name = snapshot.ToDictionary();
                nameOfPlace = name["Place Name"] as List<object>;
            }
        });

        firebaseObj.db.Collection("Points of Interest").Document("Latitude").GetSnapshotAsync().ContinueWith(task =>
        {
            DocumentSnapshot snapshot = task.Result;
            if (snapshot.Exists)
            {
                Dictionary<string, object> lat = snapshot.ToDictionary();
                placeLatitude = (lat["Latitude"] as List<object>);
            }
        });

        firebaseObj.db.Collection("Points of Interest").Document("Longitude").GetSnapshotAsync().ContinueWith(task =>
        {
            DocumentSnapshot snapshot = task.Result;
            if (snapshot.Exists)
            {
                Dictionary<string, object> lon = snapshot.ToDictionary();
                placeLongitude = lon["Longitude"] as List<object>;
            }
        });        
    }

    public void FinalFunc(float userLat, float userLon)
    {
        if(flag==1)
        {
            GetData();
            flag--;
        }
        
        if (placeLongitude.Count>0)
        {
            finalCoord2 = new List<float>();
            // Converting placeLatitude to list of float type since it's a list of object type
            finalCoord2 = GetClosestCoord((placeLatitude.ConvertAll(input => input as string)).Select(float.Parse).ToList(), (placeLongitude.ConvertAll(input => input as string)).Select(float.Parse).ToList(), userLat, userLon);
            lat.text = finalCoord2[0].ToString();
            lon.text = finalCoord2[1].ToString();
            placeName.text = place;
        }
    }

    public List<float> GetClosestCoord(List<float> placeLat, List<float> placeLon, float userLat, float userLon)
    {
        finalCoord = new List<float>();

        for (int i=0; i<placeLat.Count;i++)
        {
            // Calculates distance between user's and POI's coordinates
            float rad(float angle) => angle * ((float)Math.PI/180); // = angle * Math.Pi / 180.0d
            float havf(float diff) => (float)Math.Pow(Math.Sin(rad(diff) / 2), 2); // = sin²(diff / 2)
            final = 12745.6f * (float)(Math.Asin(Math.Sqrt(havf(userLat - placeLat[i]) + Math.Cos(rad(placeLat[i])) * Math.Cos(rad(userLat)) * havf(userLon - placeLon[i])))); // earth radius 6.372,8‬km x 2 = 12745.6

            // Storing the details of the closest POI through this if block
            if (final < close)
            {
                close = final;
                finalLat = placeLat[i];
                finalLon = placeLon[i];
                place = nameOfPlace[i].ToString();
            } 
        }
        finalCoord.Add(finalLat);
        finalCoord.Add(finalLon);
        return finalCoord;
    }
}

问题是我只能在应用程序启动时获取最近的 POI 的详细信息一次。它不会不断更新。我觉得时间复杂度可能存在问题,因为在极少数情况下,详细信息会更新(不是定期更新,仅在显示最初最接近的 POI 的详细信息后更新一次。)。我尝试过以多种方式更改代码库以降低时间复杂度,但无法真正使事情按预期进行。我真的很感激任何帮助!

android unity3d google-cloud-firestore augmented-reality latitude-longitude
© www.soinside.com 2019 - 2024. All rights reserved.