Ejemplo n.º 1
0
        private static void BenchmarkSearch(ISpatialIndex index, int rounds)
        {
            var query = new KnnQuery
            {
                Coordinate  = new GeoCoordinate(52.3667, 4.900),
                MaxDistance = 10000,
                MaxResults  = 15
            };

            Console.Write("Searching top {0} within {1} m from [{2}] .. ", query.MaxResults, query.MaxDistance, query.Coordinate);

            var total = 0L;

            var timer = new Stopwatch();

            for (int i = rounds; i > 0; i--)
            {
                timer.Restart();
                index.KnnSearch(query);
                timer.Stop();
                total += timer.ElapsedMilliseconds;
            }

            Console.WriteLine("ok ({0} ms)", total / rounds);
        }
Ejemplo n.º 2
0
        private bool IsQueryValid(KnnQuery query)
        {
            // Coordinates are required
            if (query.Coordinate == null)
            {
                return(false);
            }

            // Max results should be greater than zero
            if (query.MaxResults <= 0)
            {
                return(false);
            }

            // Max distance should be greater than zeo
            if (query.MaxDistance <= 0)
            {
                return(false);
            }

            // Other validation rules
            // Max distance shouldn't be greater than ... setttings..

            return(true);
        }
Ejemplo n.º 3
0
        private KnnQueryResult InternalKnnSearch(KnnQuery query)
        {
            // get search area
            var searchArea = GetSearchArea(query);

            // query the quadtree
            var docs = _quadTree.Search(searchArea);

            // almost done, but remember we searched a rectangle
            // so we need to exclude some of these results.
            // Let's do that while calculating the distance

            var results = new List <KnnQueryResultItem>();

            foreach (var doc in docs)
            {
                var distance = query.Coordinate.CalculateDistance(doc.Coordinates);
                if (distance <= query.MaxDistance)
                {
                    results.Add(new KnnQueryResultItem(doc, distance));
                }
            }

            // this could be done more efficiently by inserting into an ordered structure
            // unfortunatelly SortedList<> doesn't allow duplicated keys.
            // but there is definetely space for optimization here
            results.Sort((x, y) => x.Distance.CompareTo(y.Distance));

            // reduce set to max results
            results = results.Take(query.MaxResults).ToList();

            return(KnnQueryResult.Success(results));
        }
Ejemplo n.º 4
0
        public KnnQueryResult KnnSearch(KnnQuery query)
        {
            var search =
                from doc in _docs
                let distance = query.Coordinate.CalculateDistance(doc.Coordinates)
                               where distance <= query.MaxDistance
                               orderby distance
                               select new KnnQueryResultItem(doc, distance);

            // list results taking top max
            var results = search.Take(query.MaxResults).ToList();

            return(KnnQueryResult.Success(results));
        }
Ejemplo n.º 5
0
        private Boundary GetSearchArea(KnnQuery query)
        {
            var top    = query.Coordinate.Add(query.MaxDistance, 0);
            var bottom = query.Coordinate.Add(-query.MaxDistance, 0);
            var right  = query.Coordinate.Add(0, query.MaxDistance);
            var left   = query.Coordinate.Add(0, -query.MaxDistance);

            var halfLatitude  = (top.Latitude - bottom.Latitude) / 2;
            var halfLongitude = (right.Longitude - left.Longitude) / 2;

            var center     = new Point(left.Longitude + halfLongitude, bottom.Latitude + halfLatitude);
            var searchArea = new Boundary(center, halfLongitude, halfLatitude);

            // TODO: consider borders. search might need to be split into two.

            return(searchArea);
        }
Ejemplo n.º 6
0
        public KnnQueryResult KnnSearch(KnnQuery query)
        {
            if (query == null)
            {
                throw new ArgumentException("Parameter query cannot be null");
            }

            // validate query
            if (!IsQueryValid(query))
            {
                return(KnnQueryResult.Fail("Query is not valid. Please verify search parameters"));
            }

            // execute search
            var result = InternalKnnSearch(query);

            return(result);
        }
Ejemplo n.º 7
0
        public LocationSearchResults Search(LocationSearchRequest search)
        {
            // TODO: validate search parameter

            var query = new KnnQuery
            {
                Coordinate  = search.Coordinate,
                MaxDistance = search.MaxDistance,
                MaxResults  = search.MaxResults
            };

            // use spatial index to reduce data set
            var knnQueryResult = _spatialIndex.KnnSearch(query);

            if (!knnQueryResult.Results.Any())
            {
                return(LocationSearchResults.ZeroResults());
            }

            // now load entities from database
            var ids = knnQueryResult.Results.Select(i => i.Document.Id).ToArray();

            var locations = _locationRepository.FindIn(ids);

            // build return results by joining Location and Distance
            var results = new List <LocationSearchResultItem>();

            var locationsIndex = locations.ToDictionary(l => l.Id);

            foreach (var item in knnQueryResult.Results)
            {
                if (locationsIndex.ContainsKey(item.Document.Id))
                {
                    var location = locationsIndex[item.Document.Id];
                    results.Add(new LocationSearchResultItem(location, item.Distance));
                }
            }

            return(LocationSearchResults.Success(results));
        }
Ejemplo n.º 8
0
 public KnnQueryResult KnnSearch(KnnQuery query)
 {
     return(KnnQueryResult.ZeroResults());
 }