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);
}
}
}