【问题标题】:Clusters of Lat, Long that are near to each other彼此靠近的纬度、经度集群
【发布时间】:2018-04-16 07:59:31
【问题描述】:

我有一个场景,其中 N 个项目在 N 个位置(纬度、经度)交付。我想找到彼此靠近(100 米)交付的一组物品。比如说(Item1, Item9,...Item499)的交付使得它们之间的距离小于 100。 Item9 可以距离 Item499 超过 100 米,但如果它与组中的任何一个项目的距离小于 100 米,它将在该组中。

找到所有这样的组。 我希望有人指出正确的算法。然后我会努力的。首选语言是 C#

【问题讨论】:

    标签: c# google-maps geolocation geospatial


    【解决方案1】:

    下面是我找到的解决这个问题的算法here

    public class ClusterCreator
    {
        public Dictionary<int, SimpleCluster> GetClusters(List<SimpleCluster> clusterList, int maxDistance)
        {
            //LOAD DATA
            //var clusterList = new List<SimpleCluster>(); // LoadSimpleClusterList();
            //var latitudeSensitivity = 3;
            //var longitutdeSensitivity = 3;
    
            //CLUSTER THE DATA
            return ClusterTheData(clusterList, maxDistance);
        }
    
        public Dictionary<int, SimpleCluster> ClusterTheData(List<SimpleCluster> clusterList, int maxDistance)
        {
            //CLUSTER DICTIONARY
            var clusterDictionary = new Dictionary<int, SimpleCluster>();
    
            //Add the first node to the cluster list
            if (clusterList.Count > 0)
            {
                clusterDictionary.Add(clusterList[0].ID, clusterList[0]);
            }
    
            //ALGORITHM
            for (int i = 1; i < clusterList.Count; i++)
            {
                SimpleCluster combinedCluster = null;
                SimpleCluster oldCluster = null;
                foreach (var clusterDict in clusterDictionary)
                {
                    //Check if the current item belongs to any of the existing clusters
                    if (CheckIfInCluster(clusterDict.Value, clusterList[i], maxDistance))
                    {
                        //If it belongs to the cluster then combine them and copy the cluster to oldCluster variable;
                        combinedCluster = CombineClusters(clusterDict.Value, clusterList[i]);
                        oldCluster = new SimpleCluster(clusterDict.Value);
                    }
                }
    
                //This check means that no suitable clusters were found to combine, so the current item in the list becomes a new cluster.
                if (combinedCluster == null)
                {
                    //Adding new cluster to the cluster dictionary 
                    clusterDictionary.Add(clusterList[i].ID, clusterList[i]);
                }
                else
                {
                    //We have created a combined cluster. Now it is time to remove the old cluster from the dictionary and instead of it add a new cluster.
                    clusterDictionary.Remove(oldCluster.ID);
                    clusterDictionary.Add(combinedCluster.ID, combinedCluster);
                }
            }
            return clusterDictionary;
        }
    
        public static SimpleCluster CombineClusters(SimpleCluster home, SimpleCluster imposter)
        {
            //Deep copy of the home object
            var combinedCluster = new SimpleCluster(home);
            combinedCluster.LAT_LON_LIST.AddRange(imposter.LAT_LON_LIST);
            combinedCluster.NAMES.AddRange(imposter.NAMES);
    
            //Combine the data of both clusters
            //combinedCluster.LAT_LON_LIST.AddRange(imposter.LAT_LON_LIST);
            //combinedCluster.NAMES.AddRange(imposter.NAMES);
    
            //Recalibrate the new center
            combinedCluster.LAT_LON_CENTER = new LAT_LONG
            {
                LATITUDE = ((home.LAT_LON_CENTER.LATITUDE + imposter.LAT_LON_CENTER.LATITUDE) / 2.0),
                LONGITUDE = ((home.LAT_LON_CENTER.LONGITUDE + imposter.LAT_LON_CENTER.LONGITUDE) / 2.0)
            };
    
            return combinedCluster;
        }
    
        public bool CheckIfInCluster(SimpleCluster home, SimpleCluster imposter, int maxDistance)
        {
            foreach (var item in home.LAT_LON_LIST)
            {
                var sCoord = new GeoCoordinate(item.LATITUDE, item.LONGITUDE);
                var eCoord = new GeoCoordinate(imposter.LAT_LON_CENTER.LATITUDE, imposter.LAT_LON_CENTER.LONGITUDE);
                var distance = sCoord.GetDistanceTo(eCoord);
                if (distance <= maxDistance)
                    return true;
            }
            return false;
    
    
            //if ((home.LAT_LON_CENTER.LATITUDE + latitudeSensitivity) > imposter.LAT_LON_CENTER.LATITUDE
            //       && (home.LAT_LON_CENTER.LATITUDE - latitudeSensitivity) < imposter.LAT_LON_CENTER.LATITUDE
            //       && (home.LAT_LON_CENTER.LONGITUDE + longitutdeSensitivity) > imposter.LAT_LON_CENTER.LONGITUDE
            //       && (home.LAT_LON_CENTER.LONGITUDE - longitutdeSensitivity) < imposter.LAT_LON_CENTER.LONGITUDE
            //   )
            //{
            //    return true;
            //}
            //return false;
        }
    
    }
    public class SimpleCluster
    {
        #region Constructors
        public SimpleCluster(int id, string name, double latitude, double longitude)
        {
            ID = id;
            LAT_LON_CENTER = new LAT_LONG
            {
                LATITUDE = latitude,
                LONGITUDE = longitude
            };
            NAMES = new List<string>();
            NAMES.Add(name);
            LAT_LON_LIST = new List<LAT_LONG>();
            LAT_LON_LIST.Add(LAT_LON_CENTER);
        }
    
        public SimpleCluster(SimpleCluster old)
        {
            ID = old.ID;
            LAT_LON_CENTER = new LAT_LONG
            {
                LATITUDE = old.LAT_LON_CENTER.LATITUDE,
                LONGITUDE = old.LAT_LON_CENTER.LONGITUDE
            };
            LAT_LON_LIST = new List<LAT_LONG>(old.LAT_LON_LIST);
            NAMES = new List<string>(old.NAMES);
        }
        #endregion
        public int ID { get; set; }
        public List<string> NAMES { get; set; }
        public LAT_LONG LAT_LON_CENTER { get; set; }
        public List<LAT_LONG> LAT_LON_LIST { get; set; }
    }
    
    public class LAT_LONG
    {
        public double LATITUDE { get; set; }
        public double LONGITUDE { get; set; }
    }
    

    【讨论】:

    • GeoCoordinate() 类在哪里?
    • 没关系,我在System.Device.Location.GeoCoordinate 中找到了完整的.net,但是在.net Core 中有单独的包https://www.nuget.org/packages/GeoCoordinate/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 2021-10-10
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多