【问题标题】:Find closest city in list of geo-coordinate pairs [duplicate]在地理坐标对列表中查找最近的城市[重复]
【发布时间】:2021-11-26 04:00:08
【问题描述】:

假设有一个包含城市及其坐标的 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();

【问题讨论】:

  • 所有你需要做的就是想出一个算法来找到最接近的。如果你仔细想想,这真的不是那么难。您可以遍历现有项目,使用距离公式计算它们与提供点的距离,然后选择距离最短的项目。试一试。
  • 试试这个(.NET Standard 兼容):nuget.org/packages/GeoCoordinate.NetCore - 或(仅限旧的 .NET Framework):docs.microsoft.com/en-us/dotnet/api/…
  • @mason 地理坐标不使用距离公式(除非地球是平的)
  • 您有两组数字(纬度和经度)要处理。没有一套。因此,简单地找到最接近的数字是行不通的。你必须计算距离。您可能需要也可能不需要考虑地球的曲率。
  • @hatman 你内心深处知道你需要距离(或任何其他norm),因为没有办法找到“最接近”两个单独的值......但无论如何,很好知道我的第二个副本正是您要找的。​​span>

标签: c#


【解决方案1】:

有两种方法可以通过不精确的坐标找到位置。第一个解决方案是使用坐标方差,第二个是使用距离。每个人都有自己的好处,所以要明智地选择。

解决方案 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:我不建议这样做,因为这可能会造成繁重的过程,但距离实际上很重要。 您将需要使用搜索坐标遍历每个位置坐标并选择最小距离。 坐标方法从这里撕下来:Calculating Distance between two Latitude and Longitude GeoCoordinates

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)));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多