/// <summary> /// Performs the DBSCAN clustering algorithm. /// </summary> /// <param name="allPoints">Dataset</param> /// <param name="epsilon">Desired region ball radius</param> /// <param name="minPts">Minimum number of points to be in a region</param> /// <param name="clusters">returns sets of clusters, renew the parameter</param> public void ComputeClusterDbscan(T[] allPoints, double epsilon, int minPts, out HashSet <T[]> clusters) { DbscanPoint <T>[] allPointsDbscan = allPoints.Select(a => new DbscanPoint <T>(a)).ToArray(); int clusterId = 0; for (int i = 0; i < allPointsDbscan.Length; i++) { DbscanPoint <T> p = allPointsDbscan[i]; if (p.IsVisited) { continue; } p.IsVisited = true; RegionQuery(allPointsDbscan, p.ClusterPoint, epsilon, out DbscanPoint <T>[] neighborPts); if (neighborPts.Length < minPts) { p.ClusterId = (int)ClusterIds.Noise; } else { clusterId++; ExpandCluster(allPointsDbscan, p, neighborPts, clusterId, epsilon, minPts); } } clusters = new HashSet <T[]>(allPointsDbscan.Where(x => x.ClusterId > 0).GroupBy(x => x.ClusterId).Select(x => x.Select(y => y.ClusterPoint).ToArray())); }
/// <summary> /// /// </summary> /// <param name="allPoints">Dataset</param> /// <param name="point">point to be in a cluster</param> /// <param name="neighborPts">other points in same region with point parameter</param> /// <param name="clusterId">given clusterId</param> /// <param name="epsilon">Desired region ball range</param> /// <param name="minPts">Minimum number of points to be in a region</param> private void ExpandCluster(DbscanPoint <T>[] allPoints, DbscanPoint <T> point, DbscanPoint <T>[] neighborPts, int clusterId, double epsilon, int minPts) { point.ClusterId = clusterId; for (int i = 0; i < neighborPts.Length; i++) { DbscanPoint <T> pn = neighborPts[i]; if (!pn.IsVisited) { pn.IsVisited = true; RegionQuery(allPoints, pn.ClusterPoint, epsilon, out DbscanPoint <T>[] neighborPts2); } if (pn.ClusterId == (int)ClusterIds.Unclassified) { pn.ClusterId = clusterId; } } }