ATTPCROOT  0.3.0-alpha
A ROOT-based framework for analyzing data from active target detectors
triplet.cxx
Go to the documentation of this file.
1 //
2 // triplet.cpp
3 // Classes and functions for triplets of three points and
4 // computing their dissimilarity.
5 //
6 // Author: Jens Wilberg, Lukas Aymans, Christoph Dalitz
7 // Date: 2018-08-30
8 // License: see ../LICENSE
9 //
10 
11 #include "triplet.h"
12 
13 #include <algorithm>
14 #include <cmath>
15 #include <memory>
16 
17 #include "kdtree/kdtree.hpp"
18 
19 //-------------------------------------------------------------------
20 // Generates triplets from the PointCloud *cloud*.
21 // The resulting triplets are returned in *triplets*. *k* is the number
22 // of neighbores from a point, which are used for triplet generation.
23 // *n* is the number of the best triplet candidates to use. This can
24 // be lesser than *n*. *a* is the max error (1-angle) for the triplet
25 // to be a triplet candidate.
26 //-------------------------------------------------------------------
27 void generate_triplets(const PointCloud &cloud, std::vector<triplet> &triplets, size_t k, size_t n, double a)
28 {
29  std::vector<double> distances;
30  Kdtree::KdNodeVector nodes, result;
31  std::vector<size_t> indices; // save the indices so that they can be used
32  // for the KdNode constructor
33  indices.resize(cloud.size(), 0);
34 
35  // build kdtree
36  for (size_t i = 0; i < cloud.size(); ++i) {
37  indices[i] = i;
38  nodes.push_back(Kdtree::KdNode(cloud[i].as_vector(), (void *)&indices[i]));
39  }
40  Kdtree::KdTree kdtree(&nodes);
41 
42  for (size_t point_index_b = 0; point_index_b < cloud.size(); ++point_index_b) {
43  distances.clear();
44  Point point_b = cloud[point_index_b];
45 
46  std::vector<triplet> triplet_candidates;
47 
48  kdtree.k_nearest_neighbors(cloud[point_index_b].as_vector(), k, &result, &distances);
49 
50  for (size_t result_index_a = 1; result_index_a < result.size(); ++result_index_a) {
51  // When the distance is 0, we have the same point as point_b
52  if (distances[result_index_a] == 0)
53  continue;
54  Point point_a(result[result_index_a].point);
55  size_t point_index_a = *(size_t *)result[result_index_a].data;
56 
57  Point direction_ab = point_b - point_a;
58  double ab_norm = direction_ab.norm();
59  direction_ab = direction_ab / ab_norm;
60 
61  for (size_t result_index_c = result_index_a + 1; result_index_c < result.size(); ++result_index_c) {
62  // When the distance is 0, we have the same point as point_b
63  if (distances[result_index_c] == 0)
64  continue;
65  Point point_c = Point(result[result_index_c].point);
66  size_t point_index_c = *(size_t *)result[result_index_c].data;
67 
68  Point direction_bc = point_c - point_b;
69  double bc_norm = direction_bc.norm();
70  direction_bc = direction_bc / bc_norm;
71 
72  const double angle = direction_ab * direction_bc;
73 
74  // calculate error
75  const double error = 1.0f - angle;
76 
77  if (error <= a) {
78  // calculate center
79  Point center = (point_a + point_b + point_c) / 3.0f;
80 
81  // calculate direction
82  Point direction = point_c - point_b;
83  direction = direction / direction.norm();
84 
85  triplet new_triplet;
86 
87  new_triplet.point_index_a = point_index_a;
88  new_triplet.point_index_b = point_index_b;
89  new_triplet.point_index_c = point_index_c;
90  new_triplet.center = center;
91  new_triplet.direction = direction;
92  new_triplet.error = error;
93 
94  triplet_candidates.push_back(new_triplet);
95  }
96  }
97  }
98 
99  // order triplet candidates
100  std::sort(triplet_candidates.begin(), triplet_candidates.end());
101 
102  // use the n best candidates
103  for (size_t i = 0; i < std::min(n, triplet_candidates.size()); ++i) {
104  triplets.push_back(triplet_candidates[i]);
105  }
106  }
107 }
108 
109 // initialization of scale factor for triplet dissimilarity
111 {
112  this->scale = s;
113 }
114 
115 // dissimilarity measure for triplets
116 double ScaleTripletMetric::operator()(const triplet &lhs, const triplet &rhs)
117 {
118  const double perpendicularDistanceA =
119  (rhs.center - lhs.center + lhs.direction * (lhs.center - rhs.center) * lhs.direction).squared_norm();
120  const double perpendicularDistanceB =
121  (lhs.center - rhs.center + rhs.direction * (rhs.center - lhs.center) * rhs.direction).squared_norm();
122 
123  double anglecos = lhs.direction * rhs.direction;
124  if (anglecos > 1.0)
125  anglecos = 1.0;
126  if (anglecos < -1.0)
127  anglecos = -1.0;
128  if (std::fabs(anglecos) < 1.0e-8) {
129  return 1.0e+8;
130  } else {
131  return (std::sqrt(std::max(perpendicularDistanceA, perpendicularDistanceB)) / this->scale +
132  std::fabs(std::tan(std::acos(anglecos))));
133  }
134 }
Point::norm
double norm() const
Definition: pointcloud.cxx:73
ScaleTripletMetric::operator()
double operator()(const triplet &lhs, const triplet &rhs)
Definition: triplet.cxx:116
Kdtree::KdNodeVector
std::vector< KdNode > KdNodeVector
Definition: kdtree.hpp:32
f
double(* f)(double t, const double *par)
Definition: lmcurve.cxx:21
triplet::point_index_c
size_t point_index_c
Definition: triplet.h:23
Kdtree::KdTree
Definition: kdtree.hpp:68
Kdtree::KdNode
Definition: kdtree.hpp:22
Kdtree::KdTree::k_nearest_neighbors
void k_nearest_neighbors(const CoordPoint &point, size_t k, KdNodeVector *result, std::vector< double > *distances, KdNodePredicate *pred=NULL)
Definition: kdtree.cxx:295
triplet
Definition: triplet.h:20
triplet::point_index_b
size_t point_index_b
Definition: triplet.h:22
Point
Definition: main.cpp:71
triplet.h
triplet::point_index_a
size_t point_index_a
Definition: triplet.h:21
generate_triplets
void generate_triplets(const PointCloud &cloud, std::vector< triplet > &triplets, size_t k, size_t n, double a)
Definition: triplet.cxx:27
PointCloud
Definition: pointcloud.h:60
ScaleTripletMetric::ScaleTripletMetric
ScaleTripletMetric(double s)
Definition: triplet.cxx:110
triplet::error
double error
Definition: triplet.h:26
triplet::direction
Point direction
Definition: triplet.h:25
kdtree.hpp
triplet::center
Point center
Definition: triplet.h:24