using System.Collections.Generic; using System.Linq; namespace Dbscan { /// /// An implementation of the using a simple /// to hold the elements and a linear search of all items to /// for nearby items. /// /// The type of items in the index. public class ListSpatialIndex : ISpatialIndex where T : IPointData { private readonly IReadOnlyList _list; private readonly DistanceFunction _distanceFunction; /// /// Initializes a with a collection of data, using the /// Euclidean distance between two points as the distance function to search for points /// in a given neighborhood. /// /// The collection of data to put into the index public ListSpatialIndex(IEnumerable data) : this(data, (DistanceFunction)DistanceFunctions.EuclideanDistance) { } /// /// Initializes a with a collection of data, using the /// specified distanct function to search for points in a given neighborhood. /// /// The collection of data to put into the index /// The function used to determine if a point is within a specified distance of a given point. public ListSpatialIndex(IEnumerable data, DistanceFunction distanceFunction) { _list = data.ToList(); _distanceFunction = distanceFunction; } /// /// Get all of the elements within the current . /// /// /// A list of every element contained in the . /// public IReadOnlyList Search() { return _list; } /// /// Get all of the elements from this /// within a circle centered at the point /// with a radius of . /// /// The center of the search circle. /// The radius of the search circle. /// /// A list of the points that are within the search area. /// public IReadOnlyList Search(in IPointData p, double epsilon) { List list = new List(); foreach (T item in _list) { DistanceFunction distanceFunction = _distanceFunction; IPointData p2 = item; if (distanceFunction(in p, in p2) < epsilon) { list.Add(item); } } return list; } IReadOnlyList ISpatialIndex.Search(in IPointData p, double epsilon) { return Search(in p, epsilon); } } }