forked from pthimon/clustering
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClusterRotate.cpp
77 lines (67 loc) · 2.31 KB
/
ClusterRotate.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
/*
* ClusterRotate.cpp
*
* Created on: 04-Mar-2009
* Author: sbutler
*/
#include "ClusterRotate.h"
#include <map>
#include <Eigen/Array>
ClusterRotate::ClusterRotate(int method):
mMethod(method),
mMaxQuality(0)
{
}
std::vector<std::vector<int> > ClusterRotate::cluster(Eigen::MatrixXd& X) {
mMaxQuality = 0;
std::vector<std::vector<int> > clusters;
Eigen::MatrixXd vecRot;
Eigen::MatrixXd vecIn = X.block(0,0,X.rows(),2);
Evrot* e = NULL;
for (int g=2; g <= X.cols(); g++) {
// make it incremental (used already aligned vectors)
if( g > 2 ) {
vecIn.resize(X.rows(),g);
vecIn.block(0,0,vecIn.rows(),g-1) = e->getRotatedEigenVectors();
vecIn.block(0,g-1,X.rows(),1) = X.block(0,g-1,X.rows(),1);
delete e;
}
//perform the rotation for the current number of dimensions
e = new Evrot(vecIn, mMethod);
//save max quality
if (e->getQuality() > mMaxQuality) {
mMaxQuality = e->getQuality();
}
//save cluster data for max cluster or if we're near the max cluster (so prefer more clusters)
if ((e->getQuality() > mMaxQuality) || (mMaxQuality - e->getQuality() <= 0.001)) {
clusters = e->getClusters();
vecRot = e->getRotatedEigenVectors();
}
}
Eigen::MatrixXd clusterCentres = Eigen::MatrixXd::Zero(clusters.size(),vecRot.cols());
for (unsigned int i=0; i < clusters.size(); i++) {
for (unsigned int j=0; j < clusters[i].size(); j++) {
//sum points within cluster
clusterCentres.row(i) += vecRot.row(clusters[i][j]);
}
}
for (unsigned int i=0; i < clusters.size(); i++) {
//find average point within cluster
clusterCentres.row(i) = clusterCentres.row(i) / clusters[i].size();
}
//order clustered points by (ascending) distance to cluster centre
for (unsigned int i=0; i < clusters.size(); i++) {
std::multimap<double,int> clusterDistance;
for (unsigned int j=0; j < clusters[i].size(); j++) {
double d2 = (vecRot.row(clusters[i][j]) - clusterCentres.row(i)).squaredNorm();
clusterDistance.insert(std::make_pair(d2, clusters[i][j]));
}
//the map will be sorted based on the key so just loop through it
//to get set of data indices sorted on the distance to cluster
clusters[i].clear();
for (std::multimap<double,int>::iterator it = clusterDistance.begin(); it != clusterDistance.end(); it++) {
clusters[i].push_back(it->second);
}
}
return clusters;
}