ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
graph.cxx
Go to the documentation of this file.
1 //
2 // graph.cpp
3 // Classes and functions for computing the MST and for
4 // splitting up clusters at gaps
5 //
6 // Author: Jens Wilberg, Lukas Aymans, Christoph Dalitz
7 // Date: 2018-08-30
8 // License: see ../LICENSE
9 //
10 
11 #include "graph.h"
12 
13 #include "pointcloud.h" // for Point, PointCloud
14 
15 #include <algorithm>
16 #include <memory> // for allocator_traits<>::value_type
17 #include <stack>
18 
19 struct Edge {
20  size_t src, dest;
21  double weight;
22  bool operator<(const Edge &e2) const { return this->weight < e2.weight; };
23 };
24 
25 // Create edges with weights between all point indices in *cluster*. the
26 // weights are the distances of the points in *cloud*. The edges are returned
27 // in *edges*.
28 void create_edges(std::vector<Edge> &edges, const PointCloud &cloud, const std::vector<size_t> &cluster)
29 {
30  for (size_t vertex1 = 0; vertex1 < cluster.size(); ++vertex1) {
31  for (size_t vertex2 = vertex1 + 1; vertex2 < cluster.size(); ++vertex2) {
32  size_t point_index1 = cluster[vertex1], point_index2 = cluster[vertex2];
33  const Point &p = cloud[point_index1];
34  const Point &q = cloud[point_index2];
35 
36  // compute squared distance
37  double distance = (q - p).squared_norm();
38 
39  Edge e = {vertex1, vertex2, distance};
40  edges.push_back(e);
41  }
42  }
43  std::sort(edges.begin(), edges.end());
44 }
45 
46 // Create a adjacent list for every vertex from the edges in *edges*.
47 // The adjacent list is returned in *adj* which be resized to the number of
48 // vertices a priori.
49 void create_adj(std::vector<std::vector<size_t>> &adj, const std::vector<Edge> edges)
50 {
51  for (std::vector<Edge>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
52  adj[edge->src].push_back(edge->dest);
53  adj[edge->dest].push_back(edge->src);
54  }
55 }
56 
57 // Remove all edges of *edges* with weight smaller *dmax*. *edges* will be
58 // modified.
59 void remove_edge(std::vector<Edge> &edges, double dmax)
60 {
61  std::vector<Edge>::iterator edge = edges.begin();
62  double dmax2 = dmax * dmax;
63  while (edge != edges.end()) {
64  if (edge->weight > dmax2) {
65  edge = edges.erase(edge);
66  } else {
67  ++edge;
68  }
69  }
70 }
71 
72 // Remove all edges from *edges* which don't belong to the mst. *vcount* is the
73 // number of verteicies. *edges* will be modified.
74 void mst(const std::vector<Edge> &edges, std::vector<Edge> &mst_edges, size_t vcount)
75 {
76  std::vector<size_t> groups(vcount);
77  for (size_t i = 0; i < groups.size(); i++) {
78  groups[i] = i;
79  }
80 
81  for (std::vector<Edge>::const_iterator e = edges.begin(); e != edges.end(); ++e) {
82  size_t group_a = groups[e->src];
83  size_t group_b = groups[e->dest];
84 
85  // look if there is no circle
86  if (group_a != group_b) {
87  // merge groups
88  for (std::vector<size_t>::iterator it = groups.begin(); it != groups.end(); ++it) {
89  if (*it == group_b)
90  *it = group_a;
91  }
92  mst_edges.push_back(*e);
93  }
94  }
95 }
96 
97 // create a cluster of connected components which is returned in *new_cluster*.
98 // *vertex* is the index of the start vertex. *visited* is a list of the visted
99 // states from every vertecy. *cluster* is used to get the original point index
100 // of a vertex. *adj* are the adjacent lists of all vertices.
101 void dfs_util(std::vector<size_t> &new_cluster, const size_t vertex, std::vector<bool> &visited,
102  const std::vector<size_t> &cluster, const std::vector<std::vector<size_t>> &adj)
103 {
104  std::stack<size_t> stack;
105  stack.push(vertex);
106  while (!stack.empty()) {
107  size_t v = stack.top();
108  stack.pop();
109  visited[v] = true;
110  new_cluster.push_back(cluster[v]);
111 
112  for (std::vector<size_t>::const_iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
113  if (!visited[*it])
114  stack.push(*it);
115  }
116  }
117 }
118 
119 //-------------------------------------------------------------------
120 // Split *cluster* in multiple new clusters and return the result in
121 // *new_clusters". The mst of the cluster is created and all edges are
122 // removed with a wheigth > *dmax*. The connected comonents are computed
123 // and returned as new clusters if their size is >= *min_size*.
124 //-------------------------------------------------------------------
125 void max_step(std::vector<std::vector<size_t>> &new_clusters, const std::vector<size_t> &cluster,
126  const PointCloud &cloud, double dmax, size_t min_size)
127 {
128  size_t vcount = cluster.size();
129  double tstart;
130  std::vector<std::vector<size_t>> adj(vcount);
131  std::vector<Edge> edges, mst_edges;
132  std::vector<bool> visited(vcount);
133  create_edges(edges, cloud, cluster);
134  mst(edges, mst_edges, vcount);
135  remove_edge(mst_edges, dmax);
136  create_adj(adj, mst_edges);
137 
138  for (size_t v = 0; v < vcount; ++v) {
139  if (!visited[v]) {
140  std::vector<size_t> new_cluster;
141  dfs_util(new_cluster, v, visited, cluster, adj);
142  new_clusters.push_back(new_cluster);
143  }
144  }
145 }
Edge::weight
double weight
Definition: graph.cxx:21
Edge
Definition: graph.cxx:19
dfs_util
void dfs_util(std::vector< size_t > &new_cluster, const size_t vertex, std::vector< bool > &visited, const std::vector< size_t > &cluster, const std::vector< std::vector< size_t >> &adj)
Definition: graph.cxx:101
hc::cluster
std::vector< size_t > cluster
Definition: hc.h:25
mst
void mst(const std::vector< Edge > &edges, std::vector< Edge > &mst_edges, size_t vcount)
Definition: graph.cxx:74
create_adj
void create_adj(std::vector< std::vector< size_t >> &adj, const std::vector< Edge > edges)
Definition: graph.cxx:49
Point
Definition: main.cpp:71
create_edges
void create_edges(std::vector< Edge > &edges, const PointCloud &cloud, const std::vector< size_t > &cluster)
Definition: graph.cxx:28
pointcloud.h
Edge::src
size_t src
Definition: graph.cxx:20
max_step
void max_step(std::vector< std::vector< size_t >> &new_clusters, const std::vector< size_t > &cluster, const PointCloud &cloud, double dmax, size_t min_size)
Definition: graph.cxx:125
PointCloud
Definition: pointcloud.h:60
Edge::operator<
bool operator<(const Edge &e2) const
Definition: graph.cxx:22
graph.h
remove_edge
void remove_edge(std::vector< Edge > &edges, double dmax)
Definition: graph.cxx:59
Edge::dest
size_t dest
Definition: graph.cxx:20