private void CreateValidItemsAsClusters(IEnumerable items) { foreach (var item in items) { BasicGeoposition itemCoord = ConvertObjToGPS(item); if (!GeospatialHelperStatic.IsValidGPS(itemCoord)) { continue; } string id = String.Format("C{0}", this.validItemsToCluster.Count); List <Object> singleItem = new List <Object>() { item }; this.validItemsToCluster.Add(new Cluster() { ClusterId = id, Objects = singleItem, Count = 1, Location = itemCoord }); List <Object> otherSingleItem = new List <Object>() { item }; this.keyToItems.Add(id, otherSingleItem); } }
public void AddItemToClusters(Object item) { if (!GeospatialHelperStatic.IsValidGPS(ConvertObjToGPS(item))) { return; } for (int i = 1; i <= this.numZoomLevels; i++) { // List of Clusters for this zoom level ClusterList clusters = this.zoomLevelToClusters[i - 1]; bool addedToCluster = false; BasicGeoposition itemCoord = ConvertObjToGPS(item); for (int j = 0; j < clusters.Count; j++) { if (IsWithinBoundary(itemCoord, clusters[j].Location, i)) { clusters[j].Count += 1; clusters[j].Objects.Add(item); string id = String.Format("ZL{0}_C{1}", i, j); this.keyToItems[id].Add(item); addedToCluster = true; break; } } if (addedToCluster == false) { string id = String.Format("ZL{0}_C{1}", i, clusters.Count); List <Object> singleItem = new List <Object>() { item }; clusters.Add(new Cluster() { ClusterId = id, Objects = singleItem, Count = 1, Location = itemCoord }); this.keyToItems.Add(id, singleItem); } this.zoomLevelToClusters[i - 1] = clusters; } }
// Removes item from the clusters, also will need to delete clusters if they are empty public void RemoveItemFromClusters(Object item) { if (!GeospatialHelperStatic.IsValidGPS(ConvertObjToGPS(item))) { return; } for (int i = 1; i <= this.numZoomLevels; i++) { // List of Clusters for this zoom level ClusterList clusters = this.zoomLevelToClusters[i - 1]; for (int j = 0; j < clusters.Count; j++) { for (int k = 0; k < clusters[j].Objects.Count; k++) { if (item == clusters[j].Objects[k]) { // Remove the entire cluster if there is only one element if (clusters[j].Objects.Count == 1) { clusters.RemoveAt(j); } // Remove just that object from the list else { clusters[j].Objects.RemoveAt(k); } // only one object removed per zoom level and since we can't do multi-loop breaks // have this assignment to break out of the 2nd loops j = clusters.Count; break; } } } } }
// Perf? Do it by pictures first and then by zoom level? // The assumption is that the d public void GenerateClusteringData(IEnumerable items) { this.cachedConvertedObjects.Clear(); this.keyToItems.Clear(); this.zoomLevelToClusters.Clear(); this.LeastClustersZoomLevel = 1; this.MostClustersZoomLevel = 1; CreateValidItemsAsClusters(items); // 1 is space view // 20 is ground view for (int i = 1; i <= this.numZoomLevels; i++) { // List of Clusters for this zoom level ClusterList clusters = new ClusterList(); foreach (var item in items) { BasicGeoposition itemCoord = ConvertObjToGPS(item); if (!GeospatialHelperStatic.IsValidGPS(itemCoord)) { continue; } bool addedToCluster = false; for (int j = 0; j < clusters.Count; j++) { if (IsWithinBoundary(itemCoord, clusters[j].Location, i)) { clusters[j].Count += 1; clusters[j].Objects.Add(item); string id = String.Format("ZL{0}_C{1}", i, j); this.keyToItems[id].Add(item); addedToCluster = true; break; } } if (addedToCluster == false) { string id = String.Format("ZL{0}_C{1}", i, clusters.Count); List <Object> singleItem = new List <Object>() { item }; clusters.Add(new Cluster() { ClusterId = id, Objects = singleItem, Count = 1, Location = itemCoord }); List <Object> otherSingleItem = new List <Object>() { item }; this.keyToItems.Add(id, otherSingleItem); } } if (this.zoomLevelToClusters.Count > 1) { int minClusters = this.zoomLevelToClusters[this.LeastClustersZoomLevel - 1].Count; int maxClusters = this.zoomLevelToClusters[this.MostClustersZoomLevel - 1].Count; // eg: 1 1 1 3 5 5 7 7 7, this will do the 1s. See definition for what these two are if (clusters.Count <= minClusters) { this.LeastClustersZoomLevel = i; } if (clusters.Count > maxClusters) { this.MostClustersZoomLevel = i; } } this.zoomLevelToClusters.Add(clusters); } RecalculateCenters(); }