private static void Merge(Cluster source, Cluster neighbour) { double num = source.Count + neighbour.Count; source.X = ((source.Count * source.X) + (neighbour.Count * neighbour.X)) / num; source.Y = ((source.Count * source.Y) + (neighbour.Count * neighbour.Y)) / num; foreach (Feature feature in neighbour.Features) { source.Features.Add(feature); } neighbour.Features.Clear(); }
//遍历每一个点,把其归类,得到最终的聚类点Cluster,其所在格网index的X/Y组成Key private static Dictionary<int, Cluster> AssignGeoPointsToClusters(IEnumerable<Feature> features, GeoPoint bottomLeft, double diameter) { Dictionary<int, Cluster> dictionary = new Dictionary<int, Cluster>(); GeoPoint gp = null; foreach (Feature feature in features) { if (feature.Geometry == null) { continue; } if (feature.Geometry is GeoPoint) { gp = feature.Geometry as GeoPoint; } else { Rectangle2D bounds = feature.Geometry.Bounds; if (bounds.IsEmpty) { continue; } gp = new GeoPoint(bounds.Center.X, bounds.Center.Y); } double x = gp.X; double y = gp.Y; int cx = (int)Math.Round((x - bottomLeft.X) / diameter); int cy = (int)Math.Round((y - bottomLeft.Y) / diameter); int key = (cx << 16) | cy;//int是32位的 左16位是x,右16位是y if (dictionary.ContainsKey(key)) { Cluster cluster = dictionary[key]; cluster.X = (cluster.X + x) / 2.0; cluster.Y = (cluster.Y + y) / 2.0; cluster.Features.Add(feature); }//有就合并 else { dictionary[key] = new Cluster(x, y, cx, cy); dictionary[key].Features.Add(feature); }//没有就new一个 } return dictionary; }
private static bool SearchAndMerge(Cluster cluster, int ox, int oy, double diameter, Dictionary<int, Cluster> orig, bool overlapExists) { int x = cluster.Cx + ox; int y = cluster.Cy + oy; int key = (x << 16) | y; if (orig.ContainsKey(key) && (orig[key].Count > 0)) { Cluster neighbour = orig[key]; double distanceX = neighbour.X - cluster.X; double distanceY = neighbour.Y - cluster.Y; if ((Math.Sqrt((distanceX * distanceX) + (distanceY * distanceY)) < diameter) && (neighbour != cluster)) { overlapExists = true; Merge(cluster, neighbour); } } return overlapExists; }
private static Dictionary<int, Cluster> AssignGeoPointsToClusters(IEnumerable<Feature> features, ObservableCollection<GeoRegion> geos) { Dictionary<int, Cluster> dictionary = new Dictionary<int, Cluster>(); GeoPoint gp = null; foreach (Feature feature in features) { if (feature.Geometry == null) { continue; } gp = feature.Geometry as GeoPoint; if (gp == null) { Rectangle2D bounds = feature.Geometry.Bounds; if (bounds.IsEmpty) { continue; } gp = new GeoPoint(bounds.Center.X, bounds.Center.Y); } bool isContained = false; double x = gp.X; double y = gp.Y; foreach (GeoRegion clusterRegion in geos) { if (clusterRegion.Bounds.Contains(x, y) && clusterRegion.Contains(x, y)) { int key = -geos.IndexOf(clusterRegion); if (dictionary.ContainsKey(key)) { Cluster cluster = dictionary[key]; cluster.X += x; cluster.Y += y; cluster.Features.Add(feature); }//有就合并 else { dictionary[key] = new Cluster(x, y); dictionary[key].Features.Add(feature); }//没有就new一个 isContained = true; break; } } int key1 = feature.GetHashCode(); if (!isContained) { if (!dictionary.ContainsKey(key1)) { dictionary[key1] = new Cluster(gp.X, gp.Y); dictionary[key1].Features.Add(feature); } } } Cluster cltValue; int featuresCount = 0; foreach (var clt in dictionary) { cltValue = clt.Value; featuresCount = cltValue.Features.Count; clt.Value.X = cltValue.X / featuresCount; clt.Value.Y = cltValue.Y / featuresCount; } return dictionary; }