// Post
        public JsonMarkersReply Markers(
            double nelat, double nelon, double swlat, double swlon,
            int zoomlevel, string filter, int sendid
            )
        {
            var sw = new Stopwatch();

            sw.Start();

            var jsonReceive = new JsonGetMarkersReceive(nelat, nelon, swlat, swlon, zoomlevel, filter, sendid);

            var clusteringEnabled = jsonReceive.IsClusteringEnabled || AlgoConfig.AlwaysClusteringEnabledWhenZoomLevelLess > jsonReceive.Zoomlevel;

            JsonMarkersReply reply;

            jsonReceive.Viewport.ValidateLatLon(); // Validate google map viewport input (is always valid)
            jsonReceive.Viewport.Normalize();

            // Get all points from memory
            IPoints points = MemoryDatabase.GetPoints();

            if (jsonReceive.TypeFilterExclude.Count == AlgoConfig.MarkerTypes.Count)
            {
                // Filter all
                points = new Points(); // empty
            }
            else if (jsonReceive.TypeFilterExclude.Count > 0)
            {
                // Filter data by typeFilter value
                // Make new obj, don't overwrite obj data
                points = new Points
                {
                    Data = points.Data
                           .Where(p => jsonReceive.TypeFilterExclude.Contains(p.T) == false)
                           .ToList()
                };
            }

            // Create new instance for every ajax request with input all points and json data
            var clusterAlgo = new GridCluster(points, jsonReceive); // create polylines

            // Clustering
            if (clusteringEnabled && jsonReceive.Zoomlevel < AlgoConfig.ZoomlevelClusterStop)
            {
                // Calculate data to be displayed
                var clusterPoints = clusterAlgo.GetCluster(new ClusterInfo
                {
                    ZoomLevel = jsonReceive.Zoomlevel,
                });

                var converted = DataConvert(clusterPoints);

                // Prepare data to the client
                reply = new JsonMarkersReply
                {
                    Markers   = converted,
                    Rid       = sendid,
                    Polylines = clusterAlgo.Lines,
                    Msec      = Sw(sw),
                };

                // Return client data
                return(reply);
            }

            // If we are here then there are no clustering
            // The number of items returned is restricted to avoid json data overflow
            IPoints filteredDataset          = ClusterAlgorithmBase.FilterDataset(points, jsonReceive.Viewport);
            IPoints filteredDatasetMaxPoints = new Points
            {
                Data = filteredDataset.Data
                       .Take(AlgoConfig.MaxMarkersReturned)
                       .ToList()
            };

            reply = new JsonMarkersReply
            {
                Markers   = DataConvert(filteredDatasetMaxPoints),
                Rid       = sendid,
                Polylines = clusterAlgo.Lines,
                Mia       = filteredDataset.Count - filteredDatasetMaxPoints.Count,
                Msec      = Sw(sw),
            };
            return(reply);
        }