c# - 在地理坐标对列表中查找最近的城市
问题描述
假设有一个包含城市及其坐标的 JSON 文件。
{
"country": "AT",
"name": "Fladnitz im Raabtal",
"lat": "46.99167",
"lng": "15.78528"
}
我正在获取用户经度和纬度,例如纬度 46.98 和经度 15.77。现在我想在 JSON 中搜索城市和国家(在本例中为“名称”和“国家”)。但是值并不完全匹配。如何从 JSON 中获取最接近的纬度和经度值?
这是位置类
public class Location
{
public string Country { get; set; }
[JsonPropertyName("name")]
public string City { get; set; }
[JsonPropertyName("lat")]
public double Latitude { get; set; }
[JsonPropertyName("lng")]
public double Longitude { get; set; }
}
这是用于过滤的 LINQ,但我不知道如何执行“在此处获取最接近的数字操作”?
City.Text = this.Locations.Where(w => w.Latitude == lat && w.Longitude == lng)
.Select(s => s.City)
.DefaultIfEmpty("Unknown")
.First()
.ToString();
解决方案
有两种方法可以通过不精确的坐标找到位置。第一个解决方案是使用坐标方差,第二个是使用距离。每个人都有自己的好处,所以要明智地选择。
解决方案 1: 由于坐标不完全匹配,我们必须提出允许的方差。对于这个例子,我将使用 0.001 方差来表示经纬度。
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
public class Program {
public class Location {
public string Country { get; set; }
public string City { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public Location(string Country_, string City_, double Latitude_, double Longitude_){
this.Country = Country_;
this.City = City_;
this.Latitude = Latitude_;
this.Longitude = Longitude_;
}
}
public static void Main() {
List<Location> locations = new List<Location>();
locations.Add(new Location("USA", "Daytona Beach", 29.2108, 81.0228));
locations.Add(new Location("USA", "Miami", 25.7617,80.1918));
locations.Add(new Location("USA", "Jacksonville", 30.3322,81.6557));
double variance = 0.001;
double searchLat = 29.21; //unexact lat of daytona beach
Console.WriteLine(
locations.Where(w => w.Latitude >= searchLat - variance && w.Latitude <= searchLat + variance)
.Select(s => s.City)
.DefaultIfEmpty("Unknown")
.First()
.ToString()
);
}
}
解决方案 2:我真的不建议这样做,因为这可能会很繁重,但距离实际上很重要。您需要使用搜索坐标遍历每个位置坐标并选择最小距离。从这里翻录的坐标方法:计算两个纬度和经度地理坐标之间的距离
using System;
using System.Collections.Generic;
using System.Linq;
public class Program {
public class Location {
public string Country { get; set; }
public string City { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public Location(string Country_, string City_, double Latitude_, double Longitude_) {
this.Country = Country_;
this.City = City_;
this.Latitude = Latitude_;
this.Longitude = Longitude_;
}
}
static void Main(string[] args) {
List<Location> locations = new List<Location>();
locations.Add(new Location("USA", "Daytona Beach", 29.2108, 81.0228));
locations.Add(new Location("USA", "Miami", 25.7617, 80.1918));
locations.Add(new Location("USA", "Jacksonville", 30.3322, 81.6557));
double searchLat = 30;
double searchLong = 81;
Dictionary<double, List<Location>> distances = new Dictionary<double, List<Location>>();
locations.ForEach(location => {
double distance = Program.GetDistance(location.Latitude, location.Longitude, searchLat, searchLong);
if(distances.ContainsKey(distance)){
distances[distance].Add(location);
}else{
distances.Add(distance, new List<Location>() { location });
}
});
double closestDistanceFromSearch = distances.Keys.OrderBy(k => k).First();
Console.WriteLine(
distances[distances.Keys.OrderBy(k => k).First()].First().City
);
}
public static double GetDistance(double latitude, double longitude, double otherLatitude, double otherLongitude) {
var d1 = latitude * (Math.PI / 180.0);
var num1 = longitude * (Math.PI / 180.0);
var d2 = otherLatitude * (Math.PI / 180.0);
var num2 = otherLongitude * (Math.PI / 180.0) - num1;
var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0);
return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3)));
}
}
推荐阅读
- mysql - MySQL 和 MariaDB - 将表示具有许多前导零的十进制值的字符串转换为数值会产生意想不到的结果
- python - python3不能在虚拟环境中工作
- ffmpeg - ffmpeg - 从 MOV 中删除慢动作
- java - 如何使用 GWT 反转列的箭头位置
- bash - 忽略管道内的中间标准错误?
- angular - 如何获取角度组件内的所有图像,包括子组件(以及子组件...)中的图像
- docker - docker-compose + traefik - 将流量定向到 docker-compose 网络之外的服务
- filter - 可过滤的引导程序组合
- javascript - 如何使用 Yup 验证对象数组中至少一个对象键具有真实值?
- python-3.x - pytest-ordering 相对顺序不起作用?