/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static List <LocalData <T> > CloseToPoint <T>(this PointMatrix <T> matrix, Point refPt, double maxDist) { // Collect all the points within cells in range Vector range = new Vector { X = maxDist, Y = maxDist, Z = maxDist }; List <LocalData <T> > inCells = matrix.SubMatrixData <T>(Create.DiscretePoint(refPt - range, matrix.CellSize), Create.DiscretePoint(refPt + range, matrix.CellSize)); // Keep only points within maxDist distance of refPt double maxSqrDist = maxDist * maxDist; List <LocalData <T> > result = new List <LocalData <T> >(); foreach (LocalData <T> tuple in inCells) { if (tuple.Position.PMSquareDistance(refPt) < maxSqrDist) { result.Add(tuple); } } // Return final result return(result); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static List <List <T> > ClusterDBSCAN <T>(this List <T> items, Func <T, T, bool> metricFunction, int minCount = 1) { DBSCANObject <T>[] DBSCANItems = items.Select(x => Create.DBSCANObject <T>(x)).ToArray(); int c = 0; for (int i = 0; i < DBSCANItems.Length; i++) { DBSCANObject <T> p = DBSCANItems[i]; if (p.IsVisited) { continue; } p.IsVisited = true; DBSCANObject <T>[] neighbourItems = null; RegionQuery(DBSCANItems, p.ClusterItem, metricFunction, out neighbourItems); if (neighbourItems.Length < minCount) { p.ClusterId = -1; } else { c++; ExpandCluster(DBSCANItems, p, neighbourItems, metricFunction, c, minCount); } } List <List <T> > clusters = new List <List <T> >( DBSCANItems .Where(x => x.ClusterId > 0) .GroupBy(x => x.ClusterId) .Select(x => x.Select(y => y.ClusterItem).ToList()) ); return(clusters); }