void setPartner(Cell const v, Cell const w) { pairUp(v, w); std::queue<Cell> q; if (_complex.cellDimension(v) > _complex.cellDimension(w)) q.push(v); else q.push(w); while (not q.empty()) { Cell const cell = q.front(); q.pop(); for (size_t i = 0; i < _coI.count(cell); ++i) { Cell const cof = _coI(cell, i); if (_nrPairableFacets.at(cof) != 1) continue; for (size_t j = 0; j < _I.count(cof); ++j) { Cell const f = _I(cof, j); if (!_field.getDirection(f)) { pairUp(cof, f); q.push(cof); q.push(f); break; } } } } }
SmartMorseVectorField(CubicalComplex const& complex) : _complex(complex), _I(complex.xdim(), complex.ydim(), complex.zdim(), false), _coI(complex.xdim(), complex.ydim(), complex.zdim(), true), _field(complex), _nrPairableFacets(complex.cellIdLimit()) { for (Cell cell = 0; cell < complex.cellIdLimit(); ++cell) if (complex.isCell(cell)) _nrPairableFacets.at(cell) = _I.count(cell); }
bool isLocalMinimum( Cell const v, Facets const& I, Facets const& coI, Scalars const& scalars) { float const h = scalars(v); size_t const m = I.count(v); for (size_t i = 0; i < m; ++i) { Cell const e = I(v, i); size_t const k = coI.count(e); for (size_t j = 0; j < k; ++j) { Cell const w = coI(e, j); if (w != v and scalars(w) <= h) return false; } } return true; }
bool isLocalMinimum( Cell const v, Facets const& I, Facets const& coI, Vertices const& vertices, Scalars const& scalars) { float const h = cellAverage(v, scalars, vertices); size_t const m = I.count(v); for (size_t i = 0; i < m; ++i) { Cell const e = I(v, i); size_t const k = coI.count(e); for (size_t j = 0; j < k; ++j) { Cell const w = coI(e, j); if (w != v and cellAverage(w, scalars, vertices) <= h) return false; } } return true; }
VolumeData withSaturatedVectorField(VolumeData const& original) { CubicalComplex const& complex = original.complex; Facets const facets(complex.xdim(), complex.ydim(), complex.zdim(), false); Field::DataPtr const& oldData = original.field.data(); Field::DataPtr newData(new Field::DataPtr::element_type(*oldData)); Field field(complex.xdim(), complex.ydim(), complex.zdim(), newData); for (Cell start = 0; start < complex.cellIdLimit(); ++start) { if (not complex.isCell(start) or not field.isCritical(start)) continue; int const n = facets.count(start); for (int i = 0; i < n; ++i) { Cell const f = facets(start, i); if (field.isCritical(f)) field.setPartner(start, f); } } return VolumeData(complex, original.scalars, field); }
void extract( Cell const v, Facets const& cofacets, Vertices const& vertices, Scalars const& scalars) { Value value = scalars.get(v); cells_[0] = v; defined_[0] = false; weight_[0] = value; ranked_[0] = 0; incidence_counts_[0] = 0; size_ = 1; int mark = size_; int next = 0; while (next < size_) { Cell const cell = cells_[next]; int const n = cofacets.count(cell); for (int i = n - 1; i >= 0; --i) { Cell const coface = cofacets(cell, i); int k; for (k = mark; k < size_; ++k) if (coface == cells_[k]) break; if (k < size_) { incidences_[k][incidence_counts_[k]] = next; ++incidence_counts_[k]; continue; } int const m = vertices.count(coface); bool add = true; Value sum = 0.0; for (int j = 0; j < m; ++j) { Cell const w = vertices(coface, j); Value const d = scalars.get(w); if (d > value or (d == value and w > v)) { add = false; break; } sum += d; } if (add) { cells_[size_] = coface; defined_[size_] = false; weight_[size_] = sum; ranked_[size_] = size_; incidences_[size_][0] = next; incidence_counts_[size_] = 1; ++size_; if (size_ > MAX_STAR) throw starException; } } ++next; if (next == mark) mark = size_; } for (int i = 0; i < size_; ++i) { int j; Value x = weight_[i]; for (j = i; j > 0 && x < weight_[j-1]; --j) { ranked_[j] = ranked_[j-1]; weight_[j] = weight_[j-1]; } ranked_[j] = i; weight_[j] = x; } }
void update(Cell const v) { _nrPairableFacets.at(v) = 0; for (size_t i = 0; i < _coI.count(v); ++i) --_nrPairableFacets.at(_coI(v, i)); }
Result checkConnections(VolumeData const& candidate) { CubicalComplex const& complex = candidate.complex; Field const& field = candidate.field; Field::Vectors const V = field.V(); Field::Vectors const coV = field.coV(); Facets const I(complex.xdim(), complex.ydim(), complex.zdim(), false); Facets const coI(complex.xdim(), complex.ydim(), complex.zdim(), true); std::vector<Cell> const sources = criticalCells(candidate); std::shared_ptr<std::vector<bool> > marked = connectingPaths(complex, field, V, coV, I, coI); for (size_t v = 0; v < complex.cellIdLimit(); ++v) { if (not marked->at(v)) { if (complex.isCell(v) and field.isCritical(v)) { std::stringstream msg; msg << "unmarked critical cell at " << complex.cellPosition(v); return failure(msg.str()); } } else { bool good = false; if (field.isCritical(v)) { continue; } else if (V.defined(v)) { Cell const u = V(v); for (int i = 0; i < coI.count(v); ++i) { Cell const w = coI(v, i); good = good || (w != u and marked->at(w)); } } else { Cell const u = coV(v); for (int i = 0; i < I.count(v); ++i) { Cell const w = I(v, i); good = good || (w != u and marked->at(w)); } } if (not good) { std::stringstream msg; msg << "dead end at " << complex.cellPosition(v); return failure(msg.str()); } } } return success(); }