60 std::vector<ttk::DiagramType> &inputPersistenceDiagrams,
61 std::vector<std::vector<MatchingType>> &outputMatchings,
62 const std::string &algorithm,
63 const std::string &wasserstein,
71#ifdef TTK_ENABLE_OPENMP
72#pragma omp parallel for num_threads(threadNumber_)
74 for(
int i = 0; i < numInputs - 1; ++i) {
76 i, inputPersistenceDiagrams, outputMatchings,
78 wasserstein, tolerance, px, py, pz, ps, pe
88 std::vector<ttk::DiagramType> &allDiagrams,
89 std::vector<std::vector<MatchingType>> &allMatchings,
90 std::vector<trackingTuple> &trackings) {
92 auto numPersistenceDiagramsInput = (int)allDiagrams.size();
93 for(
int in = 1; in < numPersistenceDiagramsInput - 1; ++in) {
95 std::vector<MatchingType> matchings1 = allMatchings[in - 1];
96 std::vector<MatchingType> matchings2 = allMatchings[in];
98 auto matchingsSize1 = (int)matchings1.size();
99 auto matchingsSize2 = (int)matchings2.size();
101 int const endIndex = numPersistenceDiagramsInput - 2;
103 for(
int i = 0; i < matchingsSize1; ++i) {
104 const auto m1ai0 = std::get<0>(matchings1[i]);
105 const auto m1ai1 = std::get<1>(matchings1[i]);
106 for(
int j = 0; j < matchingsSize2; ++j) {
108 const auto m2aj0 = std::get<0>(matchings2[j]);
109 const auto m2aj1 = std::get<1>(matchings2[j]);
117 int const chainStart = std::get<0>(tt);
118 int const chainEnd = std::get<1>(tt);
119 std::vector<SimplexId> &chain = std::get<2>(tt);
122 auto chainSize = (int)chain.size();
126 }
else if(chainStart + chainSize == in
127 && chain.at((
unsigned long)chainSize - 1) == m1ai0) {
129 chain.push_back(m1ai1);
130 int const numEnd = in == endIndex ? endIndex : -1;
132 chain.push_back(m2aj1);
133 std::get<1>(tt) = numEnd;
135 std::get<2>(tt) = chain;
138 tt = std::make_tuple(chainStart, chainEnd, chain);
142 std::vector<SimplexId> chain;
143 chain.push_back(m1ai0);
144 chain.push_back(m1ai1);
146 chain.push_back(m2aj1);
148 int const numEnd = in == endIndex ? endIndex : -1;
149 trackingTuple const tt = std::make_tuple(in - 1, numEnd, chain);
150 trackings.push_back(tt);
158 int const chainStart = std::get<0>(tt);
159 int const chainEnd = std::get<1>(tt);
161 std::vector<SimplexId>
const &chain = std::get<2>(tt);
162 auto chainSize = (int)chain.size();
163 if(chainStart + chainSize - 1 < in)
164 std::get<1>(tt) = in - 1;
170 std::sort(trackings.begin(), trackings.end(),
172 return std::get<0>(a) < std::get<0>(b);
179 const std::vector<ttk::DiagramType> &allDiagrams,
180 const std::vector<trackingTuple> &trackings,
181 std::vector<std::set<int>> &trackingTupleToMerged,
182 const double postProcThresh) {
184 const int numPersistenceDiagramsInput = allDiagrams.size();
187 for(
size_t k = 0; k < trackings.size(); ++k) {
188 const auto &tk = trackings[k];
189 int const startK = std::get<0>(tk);
190 int endK = std::get<1>(tk);
192 endK = numPersistenceDiagramsInput - 1;
193 const std::vector<SimplexId> &chainK = std::get<2>(tk);
197 const auto n1 = chainK.front();
198 const auto n2 = chainK.back();
199 const auto &tuple1 = diagramStartK[n1];
200 const auto &tuple2 = diagramEndK[n2];
202 double x1, y1, z1, x2, y2, z2;
204 const auto point1Type1 = tuple1.birth.type;
205 const auto point1Type2 = tuple1.death.type;
211 bool const t1Max = t11Max || t12Max;
212 bool const t1Min = !t1Max && (t11Min || t12Min);
214 x1 = t1Max ? tuple1.death.coords[0] : t1Min ? tuple1.birth.coords[0] : 0;
215 y1 = t1Max ? tuple1.death.coords[1] : t1Min ? tuple1.birth.coords[1] : 0;
216 z1 = t1Max ? tuple1.death.coords[2] : t1Min ? tuple1.birth.coords[2] : 0;
218 const auto point2Type1 = tuple2.birth.type;
219 const auto point2Type2 = tuple2.death.type;
225 bool const t2Max = t21Max || t22Max;
226 bool const t2Min = !t2Max && (t21Min || t22Min);
229 x2 = t2Max ? tuple2.death.coords[0] : t2Min ? tuple2.birth.coords[0] : 0;
230 y2 = t2Max ? tuple2.death.coords[1] : t2Min ? tuple2.birth.coords[1] : 0;
231 z2 = t2Max ? tuple2.death.coords[2] : t2Min ? tuple2.birth.coords[2] : 0;
237 if(!t1Min && !t2Min && !t1Max && !t2Max)
241 for(
size_t m = k + 1; m < trackings.size(); ++m) {
242 const auto &tm = trackings[m];
243 int const startM = std::get<0>(tm);
244 int const endM = std::get<1>(tm);
245 const std::vector<SimplexId> &chainM = std::get<2>(tm);
246 if((endK > 0 && startM > endK) || (endM > 0 && startK > endM))
249 for(
int c = 0; c < (int)chainM.size(); ++c) {
250 bool const doMatch1 = startM + c == startK;
251 bool const doMatch2 = startM + c == endK;
254 if(!doMatch1 && !doMatch2)
258 const auto n3 = chainM[c];
260 const auto &tuple3 = diagramM[n3];
262 const auto point3Type1 = tuple3.birth.type;
263 const auto point3Type2 = tuple3.death.type;
271 bool const t3Max = t31Max || t32Max;
272 bool const t3Min = !t3Max && (t31Min || t32Min);
274 x3 = t3Max ? tuple3.death.coords[0]
275 : t3Min ? tuple3.birth.coords[0]
277 y3 = t3Max ? tuple3.death.coords[1]
278 : t3Min ? tuple3.birth.coords[1]
280 z3 = t3Max ? tuple3.death.coords[2]
281 : t3Min ? tuple3.birth.coords[2]
285 bool hasMatched =
false;
286 const auto square = [](
const double a) {
return a * a; };
287 if(doMatch1 && ((t3Max && t1Max) || (t3Min && t1Min))) {
289 = std::sqrt(square(x1 - x3) + square(y1 - y3) + square(z1 - z3));
291 if(dist13 >= postProcThresh)
296 if(doMatch2 && ((t3Max && t2Max) || (t3Min && t2Min))) {
298 = std::sqrt(square(x2 - x3) + square(y2 - y3) + square(z2 - z3));
300 if(dist23 >= postProcThresh)
309 std::stringstream msg;
310 msg <<
"Merged " << m <<
" with " << k <<
": d = " << dist <<
".";
314 std::set<int> &mergedM = trackingTupleToMerged[m];
int performSingleMatching(int i, std::vector< ttk::DiagramType > &inputPersistenceDiagrams, std::vector< std::vector< MatchingType > > &outputMatchings, const std::string &algorithm, const std::string &wasserstein, double tolerance, double px, double py, double pz, double ps, double pe)
int performMatchings(int numInputs, std::vector< ttk::DiagramType > &inputPersistenceDiagrams, std::vector< std::vector< MatchingType > > &outputMatchings, const std::string &algorithm, const std::string &wasserstein, double tolerance, double px, double py, double pz, double ps, double pe)