/// <summary>
		/// todo use threads and threadData
		/// </summary>
		/// <param name="points"></param>
		/// <param name="input"></param>
		public GridCluster(IList<P> points, JsonGetMarkersReceive input)
			: base(points)
		{
			this._jsonReceive = input;
            double[] deltas = GetDelta(GmcSettings.Get.Gridx, GmcSettings.Get.Gridy, input.Zoomlevel);
			DeltaX = deltas[0];
			DeltaY = deltas[1];
			Grid = GetBoundaryExtended(input);
		}
		public static Boundary GetBoundaryExtended(JsonGetMarkersReceive input)
		{            
            var deltas = GetDelta(GmcSettings.Get.Gridx, GmcSettings.Get.Gridy, input.Zoomlevel);
			var deltaX = deltas[0];
			var deltaY = deltas[1];

			// Grid with extended outer grid-area non-visible            
			var a = MathTool.FloorLatLon(input.Viewport.Minx, deltaX) - deltaX * GmcSettings.Get.OuterGridExtend;
			var b = MathTool.FloorLatLon(input.Viewport.Miny, deltaY) - deltaY * GmcSettings.Get.OuterGridExtend;
			var a2 = MathTool.FloorLatLon(input.Viewport.Maxx, deltaX) + deltaX * (1 + GmcSettings.Get.OuterGridExtend);
			var b2 = MathTool.FloorLatLon(input.Viewport.Maxy, deltaY) + deltaY * (1 + GmcSettings.Get.OuterGridExtend);

			// Latitude is special with Google Maps, they don't wrap around, then do constrain
			b = MathTool.ConstrainLatitude(b);
			b2 = MathTool.ConstrainLatitude(b2);

			var grid = new Boundary { Minx = a, Miny = b, Maxx = a2, Maxy = b2 };
			grid.Normalize();
			return grid;
		}