Belle II Software  release-08-01-10
MCParticleTrajectory.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <simulation/dataobjects/MCParticleTrajectory.h>
10 #include <TVector3.h>
11 #include <stack>
12 #include <tuple>
13 
14 using namespace Belle2;
15 
16 namespace {
24  void setVector(TVector3& v, const MCTrajectoryPoint& a, const MCTrajectoryPoint& b, bool unit = false)
25  {
26  v.SetXYZ(a.x - b.x, a.y - b.y, a.z - b.z);
27  if (unit) {
28  v *= 1. / v.Mag();
29  }
30  }
31 }
32 
33 void MCParticleTrajectory::simplify(float distance_tolerance)
34 {
35  // cannot simplify anything, return
36  if (distance_tolerance <= 0 || m_points.size() < 3) return;
37 
38  // stack with all segments to be investigated
39  std::stack<std::pair<iterator, iterator>> stack;
40  // push full trajectory on the stack
41  stack.push(make_pair(m_points.begin(), m_points.end() - 1));
42  // next free point: we always want the starting point so start at index 1
43  iterator nextFreePoint = m_points.begin() + 1;
44  // iterators used for the segment inspection
45  iterator firstPoint, splitPoint, finalPoint;
46  // segment direction and vector between segment start and mid point
47  TVector3 n, pa;
48  // investigate all segments until all fulfill the distance requirement
49  while (!stack.empty()) {
50  //Get first and last point
51  std::tie(firstPoint, finalPoint) = stack.top();
52  //Remove segment from stack
53  stack.pop();
54  //Direction of the segment
55  setVector(n, *firstPoint, *finalPoint, true);
56  //Calculate maximum distance of all intermediate points to the segment
57  double maxDistance(0);
58  for (auto nextPoint = firstPoint + 1; nextPoint != finalPoint; ++nextPoint) {
59  //vector from segment start (p) to point (a)
60  setVector(pa, *firstPoint, *nextPoint);
61  //3D distance between point a and line p + x*n
62  const double dist = (pa - (pa * n) * n).Mag();
63  //check if this is the maximum distance so far
64  if (dist > maxDistance) {
65  splitPoint = nextPoint;
66  maxDistance = dist;
67  }
68  }
69  //Are all points close enough? if not split the segment at the largest distance
70  if (maxDistance > distance_tolerance) {
71  //If we split in this order, all points will be in correct order since we
72  //use a stack: last thing put in is first thing to get out. So initially
73  //we inspect everything, if we divide we put in the second part and then
74  //the first and in the next round we take out the first and repeat. So
75  //effectively we look at all segments in an ordered way.
76  stack.push(make_pair(splitPoint, finalPoint));
77  stack.push(make_pair(firstPoint, splitPoint));
78  continue;
79  }
80  //Ok, all points close enough, add the final point to list of points. Due
81  //to the order in which we look at the points in a ordered way we can
82  //replace the points in place
83  *(nextFreePoint++) = *finalPoint;
84  }
85 
86  //Now delete all remaining elements
87  m_points.erase(nextFreePoint, end());
88 }
std::vector< MCTrajectoryPoint >::iterator iterator
iterator definition to allow iteration
iterator end()
return iterator beyond the last point
void simplify(float distanceTolerance)
Simplify the trajectory using the Ramer-Douglas-Peuker algorithm.
std::vector< MCTrajectoryPoint > m_points
Collection of points along the trajectory.
Abstract base class for different kinds of events.
Small struct to encode a position/momentum without additional overhead.