/// <summary>
        /// clusters retrieved pins geographically
        /// </summary>
        /// <param name="pins"></param>
        /// <param name="zoomLevel"></param>
        /// <param name="clusterWidth"></param>
        /// <param name="clusterHeight"></param>
        /// <returns></returns>
        public List <ClusteredPin> cluster(List <ClusteredPin> pins, int zoomLevel, int clusterWidth, int clusterHeight)
        {
            //sort pins - must be ordered correctly.
            PinXYComparer pinComparer = new PinXYComparer();

            pins.Sort(pinComparer);

            List <ClusteredPin> clusteredPins = new List <ClusteredPin>();

            for (int index = 0; index < pins.Count; index++)
            {
                if ((!pins[index].IsClustered))     //skip already clusted pins
                {
                    ClusteredPin currentClusterPin = new ClusteredPin();
                    //create our cluster object and add the first pin
                    currentClusterPin.AddPin(pins[index]);
                    pins[index].IsClustered = true;

                    //look backwards in the list for any points within the range that are not already grouped, as the points are in order we exit as soon as it exceeds the range.
                    addPinsWithinRange(pins, index, -1, currentClusterPin, zoomLevel, clusterWidth, clusterHeight);

                    //look forwards in the list for any points within the range, again we short out.
                    addPinsWithinRange(pins, index, 1, currentClusterPin, zoomLevel, clusterWidth, clusterHeight);

                    clusteredPins.Add(currentClusterPin);
                }
            }
            return(clusteredPins);
        }
        /// <summary>
        /// clusteres visually
        /// </summary>
        /// <param name="clusteredpins"></param>
        /// <param name="zoomLevel"></param>
        /// <param name="minClusterDistance"></param>
        /// <returns></returns>
        private List <ClusteredPin> reduceClusterDensity(List <ClusteredPin> clusteredpins, int zoomLevel, int minClusterDistance)
        {
            PinXYComparer pinComparer = new PinXYComparer();

            clusteredpins.Sort(pinComparer);
            List <ClusteredPin> pins = new List <ClusteredPin>();

            //reset flag
            //Only cluster already clusteredpoints and do not cluster Alerts
            for (int j = 0; j < clusteredpins.Count; j++)
            {
                if (clusteredpins[j].PinType == "clusterpoint")
                {
                    clusteredpins[j].IsClustered = false;
                }
                else
                {
                    clusteredpins[j].IsClustered = true;
                    pins.Add(clusteredpins[j]);
                }
            }
            for (int i = 0; i < clusteredpins.Count; i++)
            {
                if ((!clusteredpins[i].IsClustered)) //skip already clusted pins
                {
                    ClusteredPin currentClusterPin = new ClusteredPin();
                    //create our cluster object and add the first pin
                    currentClusterPin.AddPin(clusteredpins[i]);


                    //look backwards in the list for any points within the range that are not already grouped, as the points are in order we exit as soon as it exceeds the range.
                    addClusteredPinsWithinRange(clusteredpins, i, -1, clusteredpins[i], zoomLevel, minClusterDistance);

                    //look forwards in the list for any points within the range, again we short out.
                    addClusteredPinsWithinRange(clusteredpins, i, 1, clusteredpins[i], zoomLevel, minClusterDistance);

                    clusteredpins[i].IsClustered = true;

                    pins.Add(clusteredpins[i]);
                }
            }
            return(pins);
        }