// O(k*n)
            List <XY> RunClusterAlgo()
            {
                // put points in buckets
                int allPointsCount = BaseDataset.Count;
                var firstPoint     = BaseDataset[0];

                firstPoint.Color = GetRandomColor();
                var firstId     = 0.ToString();
                var firstBucket = new Bucket(firstId)
                {
                    Centroid = firstPoint
                };

                BaseBucketsLookup.Add(firstId, firstBucket);

                for (int i = 1; i < allPointsCount; i++)
                {
                    var set = new HashSet <string>();    //cluster candidate list
                    var p   = BaseDataset[i];
                    // iterate clusters and collect candidates
                    foreach (var bucket in BaseBucketsLookup.Values)
                    {
                        var isInCluster = MathTool.BoxWithin(p, bucket.Centroid, MARKERCLUSTERER_SIZE);
                        if (!isInCluster)
                        {
                            continue;
                        }

                        set.Add(bucket.Id);
                        //use first, short dist will be calc at last step before returning data
                        break;
                    }

                    // if not within box area, then make new cluster
                    if (set.Count == 0)
                    {
                        var pid = i.ToString();
                        p.Color = GetRandomColor();
                        var newbucket = new Bucket(pid)
                        {
                            Centroid = p
                        };
                        BaseBucketsLookup.Add(pid, newbucket);
                    }
                }

                //important, align all points to closest cluster point
                BaseUpdatePointsByCentroid();

                return(BaseGetClusterResult());
            }