Belle II Software development
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 <Math/Vector3D.h>
11#include <stack>
12#include <tuple>
13
14using namespace Belle2;
15
16namespace {
24 void setVector(ROOT::Math::XYZVector& 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.R();
29 }
30 }
31}
32
33void 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 ROOT::Math::XYZVector 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.Dot(n)) * n).R();
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.