Distribution combine(Distribution const& c, InfoMap const& info) { std::map<Cell, Value> tmp; for (size_t i = 0; i < c.size(); ++i) { Distribution const& w = info(c.at(i).first)->weights; Value const f = c.at(i).second; for (size_t j = 0; j < w.size(); ++j) { Cell const v = w.at(j).first; if (tmp.count(v) == 0) tmp[v] = 0; tmp[v] += f * w.at(j).second; } } Distribution result(tmp.size()); std::map<Cell, Value>::const_iterator iter = tmp.begin(); for (size_t i = 0; i < tmp.size(); ++i, ++iter) result[i] = std::make_pair(iter->first, iter->second); return result; }
Mask boundaries( CubicalComplex const& complex, Scalars const& scalars) { Facets I(complex.xdim(), complex.ydim(), complex.zdim(), false); Facets coI(complex.xdim(), complex.ydim(), complex.zdim(), true); VertexQueue queue; InfoMap info(complex); Mask result(complex); for (Cell v = 0; v < complex.cellIdLimit(); ++v) { if (complex.isCell(v) and complex.cellDimension(v) == 0 and isLocalMinimum(v, coI, I, scalars)) { queue.push(v, scalars(v) + 1); info.set(v, InfoPtr(new VertexInfo())); result.set(v, 2); } } while (not queue.empty()) { Cell const v = queue.top(); queue.pop(); size_t const m = coI.count(v); std::vector<size_t> lower; for (size_t i = 0; i < m; ++i) { Cell const w = opposite(coI(v, i), v, I); if (not info(w)) { queue.push(w, scalars(w)); info.set(w, InfoPtr(new VertexInfo())); } else if (info(w)->active) lower.push_back(w); } info(v)->active = true; info(v)->countDown = m - lower.size(); if (lower.size() == 0) { info(v)->weights = Distribution(1); info(v)->weights.at(0) = std::make_pair(v, 1); info(v)->basin = v; } else { Distribution const dist = derivedDistribution(v, lower, info, scalars); info(v)->weights = dist; std::set<size_t> seen; for (size_t i = 0; i < lower.size(); ++i) seen.insert(info(lower.at(i))->basin); std::pair<size_t, Value> best; size_t count = 0; for (size_t i = 0; i < dist.size(); ++i) if (seen.count(dist.at(i).first) > 0) if (++count == 1 or dist.at(i).second > best.second) best = dist.at(i); info(v)->basin = best.first; } for (size_t i = 0; i < lower.size(); ++i) { Cell const w = lower.at(i); if (info(v)->basin != info(w)->basin and scalars(v) <= 0) result.set(std::min(v, w), 1); if (--(info(w)->countDown) == 0) info.set(w, InfoPtr()); } } return result; }