static List <PointInfo> GetRegion(List <PointInfo> points, PointInfo p, double eps) { List <PointInfo> region = new List <PointInfo>(); for (int i = 0; i < points.Count; i++) { int distSquared = PointInfo.DistanceSquared(p, points[i]); if (distSquared <= eps) { region.Add(points[i]); } } return(region); }
//**********************************DBSCAN Alghorithm ******************************************************* static public List <List <PointInfo> > GetClusters(List <PointInfo> points, double eps, int minPts) { if (points == null) { return(null); } List <List <PointInfo> > clusters = new List <List <PointInfo> >(); eps *= eps; // square eps int clusterId = 1; for (int i = 0; i < points.Count; i++) { PointInfo p = points[i]; if (p.ClusterId == PointInfo.UNCLASSIFIED) { if (ExpandCluster(points, p, clusterId, eps, minPts)) { clusterId++; } } } // sort out points into their clusters, if any int maxClusterId = points.OrderBy(p => p.ClusterId).Last().ClusterId; if (maxClusterId < 1) { return(clusters); // no clusters, so list is empty } for (int i = 0; i < maxClusterId; i++) { clusters.Add(new List <PointInfo>()); } foreach (PointInfo p in points) { if (p.ClusterId > 0) { clusters[p.ClusterId - 1].Add(p); } } return(clusters); }
static bool ExpandCluster(List <PointInfo> points, PointInfo p, int clusterId, double eps, int minPts) { List <PointInfo> seeds = GetRegion(points, p, eps); if (seeds.Count < minPts) // no core point { p.ClusterId = PointInfo.NOISE; return(false); } else // all points in seeds are density reachable from point 'p' { for (int i = 0; i < seeds.Count; i++) { seeds[i].ClusterId = clusterId; } seeds.Remove(p); while (seeds.Count > 0) { PointInfo currentP = seeds[0]; List <PointInfo> result = GetRegion(points, currentP, eps); if (result.Count >= minPts) { for (int i = 0; i < result.Count; i++) { PointInfo resultP = result[i]; if (resultP.ClusterId == PointInfo.UNCLASSIFIED || resultP.ClusterId == PointInfo.NOISE) { if (resultP.ClusterId == PointInfo.UNCLASSIFIED) { seeds.Add(resultP); } resultP.ClusterId = clusterId; } } } seeds.Remove(currentP); } return(true); } }