我正在 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,8km 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 的详细信息后更新一次。)。我尝试过以多种方式更改代码库以降低时间复杂度,但无法真正使事情按预期进行。我真的很感激任何帮助!