#c# #xamarin #xamarin.forms
#c# #xamarin #xamarin.forms
Вопрос:
В настоящее время я работаю с широтой, lng между разными местоположениями и собираю расстояние между двумя разными точками. Я успешно определяю расстояние между разными точками, где я в настоящее время сортирую их по ближайшему расстоянию (в километре).
Однако я борюсь с тем, чтобы получить правильное имя на правильном расстоянии (которое составляется из двух разных lat, lngs, которые находятся в той же строке, что и имя).
Итак, одна строка в БД выглядит следующим образом (у меня около 10 разных строк с разными местоположениями с их правильной широтой, длиной):
Lat ———— Спг ——— Наименование
45.032 —14.323112—— Исландия
Затем я беру это значение широты, Lng и с помощью приведенного ниже кода получаю текущее положение пользователя в широте, lng, а затем сравниваю расстояние между текущим значением широты пользователя, положением lng, и из него у меня есть значение int, равное километру до ближайшего расстояния.
Как я могу теперь соединить это расстояние с правильным именем?
string thename;
string areaLat;
string areaLng;
double storeLat;
double storeLng;
double thedistancebetweenobjects;
async void loadareas()
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await CrossGeolocator.Current.GetPositionAsync(10000); //using a plugin that gives me the users current lat, lng.
List <int> theInts = new List<int>();
var getarea = await phpApi.getAreas(); //my db-callout
foreach (var myitems in getarea["results"])
{
thename = myitems["Name"].ToString();
areaLat = myitems["Lat"].ToString();
areaLng = myitems["Lng"].ToString();
storeLat = Double.Parse(areaLat, CultureInfo.InvariantCulture);
storeLng = Double.Parse(areaLng, CultureInfo.InvariantCulture);
thedistancebetweenobjects = distance(position.Latitude, position.Longitude,storeLat, storeLng, 'K'); //so the users current position lat lng, and then the lat (storelat), and lng (storelng) i get from the db.
int someOtherInt = Convert.ToInt32(thedistancebetweenobjects); //converting double to int
theInts.Add(someOtherInt);
}
int TheSmallestInt = theInts.Min();
System.Diagnostics.Debug.WriteLine(TheSmallestInt);
//I succesfully get the smallest int out. But how do I connect this int with the correct name from the db?
}
И это функция, которая принимает два разных значения lat, lng и дает мне результат расстояния в километре:
private double distance(double lat1, double lon1, double lat2, double lon2, char unit)
{
double theta = lon1 - lon2;
double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2))
Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
dist = Math.Acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
if (unit == 'K')
{
dist = dist * 1.609344;
}
else if (unit == 'N')
{
dist = dist * 0.8684;
}
return (dist);
}
private double deg2rad(double deg)
{
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad)
{
return (rad / Math.PI * 180.0);
}
Ответ №1:
string closest = string.Empty;
int dist = int.MaxValue;
foreach (var myitems in getarea["results"])
{
thename = myitems["Name"].ToString();
// do all of your calcs here
int someOtherInt = Convert.ToInt32(thedistancebetweenobjects);
// for every loc, check if it is closer than the previous loc
// if it is, save it's name.
if (someOtherInt < dist) {
dist = someOtherInt;
closest = thename;
}
theInts.Add(someOtherInt);
}
Ответ №2:
Я вижу, что вы используете формулу Haversine, которая в данном случае является правильным способом, которым я бы это сделал.
Что я бы сделал, так это перебирал ваш список местоположений, пока вы не дойдете до ближайшего
List<double> distList = new List<double>(); //Create a list to store distance values
List<cityLocations> locList = new List<cityLocations>();
distList.Add(50000000); // default huge distance to compare against
foreach (var city in cityList)
{
//diff between longitudes
double theta = (double)ci.longitude - (double)ll.longitude;
//harversine implimentation
double dist = Math.Sin(Utils.deg2rad(ci.latitude)) * Math.Sin(Utils.deg2rad((double)ll.latitude)) Math.Cos(Utils.deg2rad(ci.latitude)) * Math.Cos(Utils.deg2rad((double)ll.latitude)) * Math.Cos(Utils.deg2rad(theta));
dist = Math.Acos(dist);
dist = Utils.rad2deg(dist);
dist = dist * 60 * 1.1515;
if (dist < distList[0])
{
//always keep 1 record in list
distList.RemoveAt(0);
distList.Add(dist);
if (locList.Count > 0)
{
locList.RemoveAt(0);
}
locList.Add(new cityLocations { cityName = ll.cityName, latitude = ll.latitude, longitude = ll.longitude, country = ll.country });
}
}
Не самый красивый или эффективный способ сделать это любыми способами
Комментарии:
1. Я заставил это работать с решением Джейсона! Похоже, это тоже работает хорошо!