public IPoints RunClusterAlgo(ClusterInfo clusterInfo) { // Skip points outside the grid IPoints filtered = clusterInfo.IsFilterData ? FilterDataset(Dataset, Grid) : Dataset; // Put points in buckets foreach (var p in filtered.Data) { var idxy = GetPointMappedIds(p, Grid, DeltaX, DeltaY); var idx = idxy[0]; var idy = idxy[1]; // Bucket id var id = GetId(idx, idy); // Bucket exists, add point if (BucketsLookup.ContainsKey(id)) { BucketsLookup[id].Points.Add(p); } // New bucket, create and add point else { var bucket = new Bucket(idx, idy, id); bucket.Points.Add(p); BucketsLookup.Add(id, bucket); } } // Calculate centroid for all buckets SetCentroidForAllBuckets(BucketsLookup.Values); // Merge if gridpoint is to close if (AlgoConfig.DoMergeGridIfCentroidsAreCloseToEachOther) MergeClustersGrid(); if (AlgoConfig.DoUpdateAllCentroidsToNearestContainingPoint) UpdateAllCentroidsToNearestContainingPoint(); // Check again // Merge if gridpoint is to close if (AlgoConfig.DoMergeGridIfCentroidsAreCloseToEachOther && AlgoConfig.DoUpdateAllCentroidsToNearestContainingPoint) { MergeClustersGrid(); // And again set centroid to closest point in bucket UpdateAllCentroidsToNearestContainingPoint(); } return GetClusterResult(Grid); }
// Update centroid location to nearest point, // e.g. if you want to show cluster point on a real existing point area // O(n) public void UpdateCentroidToNearestContainingPoint(Bucket bucket) { if (bucket == null || bucket.Centroid == null || bucket.Points == null || bucket.Points.Count == 0) { return; } var closest = GetClosestPoint(bucket.Centroid, bucket.Points); bucket.Centroid.X = closest.X; // no normalize, points are already normalized by default bucket.Centroid.Y = closest.Y; }