-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathdbscan.cpp
99 lines (71 loc) · 2.3 KB
/
dbscan.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "dbscan.h"
#include <math.h>
#include <algorithm>
static const inline double distance(double x1, double y1, double x2, double y2)
{
double dx = x2 - x1;
double dy = y2 - y1;
return sqrt(dx * dx + dy * dy);
}
const inline int region_query(const std::vector<Point> &input, int p, std::vector<int> &output, double eps)
{
for(int i = 0; i < (int)input.size(); i++){
if(distance(input[i].x, input[i].y, input[p].x, input[p].y) < eps){
output.push_back(i);
}
}
return output.size();
}
bool expand_cluster(const std::vector<Point> &input, int p, std::vector<int> &output, int cluster, double eps, int min)
{
std::vector<int> seeds;
if(region_query(input, p, seeds, eps) < min){
//this point is noise
output[p] = -1;
return false;
}else{
//set cluster id
for(int i = 0; i < (int)seeds.size(); i++){
output[seeds[i]] = cluster;
}
//delete paint from seeds
seeds.erase(std::remove(seeds.begin(), seeds.end(), p), seeds.end());
//seed -> empty
while((int)seeds.size() > 0){
int cp = seeds.front();
std::vector<int> result;
if(region_query(input, cp, result, eps) >= min){
for(int i = 0; i < (int)result.size(); i++){
int rp = result[i];
//this paint is noise or unmarked point
if(output[rp] < 1){
//unmarked point
if(!output[rp]){
seeds.push_back(rp);
}
//set cluster id
output[rp] = cluster;
}
}
}
//delete point from seeds
seeds.erase(std::remove(seeds.begin(), seeds.end(), cp), seeds.end());
}
}
return true;
}
int dbscan(const std::vector<Point> &input, std::vector<int> &labels, double eps, int min)
{
int size = input.size();
int cluster = 1;
std::vector<int> state(size);
for(int i = 0; i < size; i++){
if(!state[i]){
if(expand_cluster(input, i, state, cluster, eps, min)){
cluster++;
}
}
}
labels = state;
return cluster - 1;
}