12 std::array<ttk::SimplexId, n>
verts;
15static void computeEdges(std::vector<ttk::SimplexId> &connectivity,
16 std::vector<double> &diameters,
18 const std::vector<std::vector<double>> &distanceMatrix,
23 std::vector<std::vector<LocCell<1>>> edges(distanceMatrix.size());
25#ifdef TTK_ENABLE_OPENMP
26#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
28 for(
size_t i = 0; i < distanceMatrix.size(); ++i) {
29 for(
size_t j = i + 1; j < distanceMatrix.size(); ++j) {
30 if(distanceMatrix[i][j] < epsilon) {
38 std::vector<size_t> psum(edges.size() + 1);
39 for(
size_t i = 0; i < edges.size(); ++i) {
40 psum[i + 1] = psum[i] + edges[i].size();
43 const auto nCells{psum.back()};
44 diameters.resize(nCells);
45 connectivity.resize(2 * nCells);
47#ifdef TTK_ENABLE_OPENMP
48#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
50 for(
size_t i = 0; i < edges.size(); ++i) {
51 for(
size_t j = 0; j < edges[i].size(); ++j) {
52 connectivity[2 * (psum[i] + j) + 0] =
static_cast<ttk::SimplexId>(i);
53 connectivity[2 * (psum[i] + j) + 1] = edges[i][j].verts[0];
54 diameters[psum[i] + j] = edges[i][j].diam;
59static inline void maxAssign(
double &a,
const double b) {
66 computeTriangles(std::vector<ttk::SimplexId> &connectivity,
67 std::vector<double> &diameters,
69 const std::vector<std::vector<double>> &distanceMatrix,
74 std::vector<std::vector<LocCell<2>>> triangles(distanceMatrix.size());
76#ifdef TTK_ENABLE_OPENMP
77#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
79 for(
size_t i = 0; i < distanceMatrix.size(); ++i) {
80 for(
size_t j = i + 1; j < distanceMatrix.size(); ++j) {
81 if(distanceMatrix[i][j] > epsilon) {
84 for(
size_t k = j + 1; k < distanceMatrix.size(); ++k) {
85 if(distanceMatrix[i][k] > epsilon || distanceMatrix[j][k] > epsilon) {
88 auto diam{distanceMatrix[i][j]};
89 maxAssign(diam, distanceMatrix[i][k]);
90 maxAssign(diam, distanceMatrix[j][k]);
91 triangles[i].emplace_back(
92 LocCell<2>{diam, std::array<ttk::SimplexId, 2>{
100 std::vector<size_t> psum(triangles.size() + 1);
101 for(
size_t i = 0; i < triangles.size(); ++i) {
102 psum[i + 1] = psum[i] + triangles[i].size();
105 const auto nCells{psum.back()};
106 diameters.resize(nCells);
107 connectivity.resize(3 * nCells);
109#ifdef TTK_ENABLE_OPENMP
110#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
112 for(
size_t i = 0; i < triangles.size(); ++i) {
113 for(
size_t j = 0; j < triangles[i].size(); ++j) {
114 connectivity[3 * (psum[i] + j) + 0] =
static_cast<ttk::SimplexId>(i);
115 connectivity[3 * (psum[i] + j) + 1] = triangles[i][j].verts[0];
116 connectivity[3 * (psum[i] + j) + 2] = triangles[i][j].verts[1];
117 diameters[psum[i] + j] = triangles[i][j].diam;
123 computeTetras(std::vector<ttk::SimplexId> &connectivity,
124 std::vector<double> &diameters,
125 const double epsilon,
126 const std::vector<std::vector<double>> &distanceMatrix,
127 const int nThreads) {
131 std::vector<std::vector<LocCell<3>>> tetras(distanceMatrix.size());
133#ifdef TTK_ENABLE_OPENMP
134#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
136 for(
size_t i = 0; i < distanceMatrix.size(); ++i) {
137 for(
size_t j = i + 1; j < distanceMatrix.size(); ++j) {
138 if(distanceMatrix[i][j] > epsilon) {
141 for(
size_t k = j + 1; k < distanceMatrix.size(); ++k) {
142 if(distanceMatrix[i][k] > epsilon || distanceMatrix[j][k] > epsilon) {
145 for(
size_t l = k + 1; l < distanceMatrix.size(); ++l) {
146 if(distanceMatrix[i][l] > epsilon || distanceMatrix[j][l] > epsilon
147 || distanceMatrix[k][l] > epsilon) {
150 auto diam{distanceMatrix[i][j]};
151 maxAssign(diam, distanceMatrix[i][k]);
152 maxAssign(diam, distanceMatrix[i][l]);
153 maxAssign(diam, distanceMatrix[j][k]);
154 maxAssign(diam, distanceMatrix[j][l]);
155 maxAssign(diam, distanceMatrix[k][l]);
156 tetras[i].emplace_back(
157 LocCell<3>{diam, std::array<ttk::SimplexId, 3>{
167 std::vector<size_t> psum(tetras.size() + 1);
168 for(
size_t i = 0; i < tetras.size(); ++i) {
169 psum[i + 1] = psum[i] + tetras[i].size();
172 const auto nCells{psum.back()};
173 diameters.resize(nCells);
174 connectivity.resize(4 * nCells);
176#ifdef TTK_ENABLE_OPENMP
177#pragma omp parallel for num_threads(nThreads) schedule(dynamic)
179 for(
size_t i = 0; i < tetras.size(); ++i) {
180 for(
size_t j = 0; j < tetras[i].size(); ++j) {
181 connectivity[4 * (psum[i] + j) + 0] =
static_cast<ttk::SimplexId>(i);
182 connectivity[4 * (psum[i] + j) + 1] = tetras[i][j].verts[0];
183 connectivity[4 * (psum[i] + j) + 2] = tetras[i][j].verts[1];
184 connectivity[4 * (psum[i] + j) + 3] = tetras[i][j].verts[2];
185 diameters[psum[i] + j] = tetras[i][j].diam;
191 double *
const density,
192 const std::vector<std::vector<double>> &distanceMatrix)
const {
194 const auto sq = [](
const double a) ->
double {
return a * a; };
196#ifdef TTK_ENABLE_OPENMP
197#pragma omp parallel for num_threads(this->threadNumber_)
199 for(
size_t i = 0; i < distanceMatrix.size(); ++i) {
201 for(
size_t j = 0; j < distanceMatrix.size(); ++j) {
206 += std::exp(-sq(distanceMatrix[i][j]) / (2.0 * sq(this->StdDev)));
215 std::array<double *const, 3> diamStats,
216 const std::vector<SimplexId> &connectivity,
217 const std::vector<double> &cellDiameters)
const {
219 const auto nCells{cellDiameters.size()};
220 if(nCells != connectivity.size() / (this->OutputDimension + 1)) {
221 this->printErr(
"Cell number mismatch");
225 std::vector<size_t> nCellsAroundVert(nPoints, 0);
227#ifdef TTK_ENABLE_OPENMP
228#pragma omp parallel for num_threads(this->threadNumber_)
231 diamStats[0][i] = this->Epsilon;
232 diamStats[1][i] = 0.0;
233 diamStats[2][i] = 0.0;
236 for(
size_t i = 0; i < nCells; ++i) {
237 for(
int j = 0; j < this->OutputDimension + 1; ++j) {
238 const auto p{connectivity[i * (this->OutputDimension + 1) + j]};
239 nCellsAroundVert[p]++;
240 diamStats[0][p] = std::min(diamStats[0][p], cellDiameters[i]);
241 diamStats[1][p] += cellDiameters[i];
242 diamStats[2][p] = std::max(diamStats[2][p], cellDiameters[i]);
246#ifdef TTK_ENABLE_OPENMP
247#pragma omp parallel for num_threads(this->threadNumber_)
250 if(nCellsAroundVert[i] == 0) {
251 diamStats[0][i] = 0.0;
252 diamStats[1][i] = 0.0;
253 diamStats[2][i] = 0.0;
255 diamStats[1][i] /= nCellsAroundVert[i];
263 std::vector<SimplexId> &connectivity,
264 std::vector<double> &diameters,
265 std::array<double *const, 3> diamStats,
266 const std::vector<std::vector<double>> &distanceMatrix,
267 double *
const density)
const {
271 if(distanceMatrix.empty()
272 || distanceMatrix.size() != distanceMatrix[0].size()) {
273 this->printErr(
"Invalid distance matrix");
279 if(this->OutputDimension == 1) {
280 computeEdges(connectivity, diameters, this->Epsilon, distanceMatrix,
281 this->threadNumber_);
282 }
else if(this->OutputDimension == 2) {
283 computeTriangles(connectivity, diameters, this->Epsilon, distanceMatrix,
284 this->threadNumber_);
285 }
else if(this->OutputDimension == 3) {
286 computeTetras(connectivity, diameters, this->Epsilon, distanceMatrix,
287 this->threadNumber_);
290 this->
printMsg(
"Generated Rips complex from distance matrix", 1.0,
291 tm_rips.getElapsedTime(), this->threadNumber_,
294 this->computeDiameterStats(
295 distanceMatrix.size(), diamStats, connectivity, diameters);
297 if(this->ComputeGaussianDensity) {
298 this->computeGaussianDensity(density, distanceMatrix);
301 this->
printMsg(
"Complete", 1.0, tm.getElapsedTime(), this->threadNumber_);
#define TTK_FORCE_USE(x)
Force the compiler to use the function/method parameter.
void setDebugMsgPrefix(const std::string &prefix)
int computeGaussianDensity(double *const density, const std::vector< std::vector< double > > &distanceMatrix) const
Compute Gaussian density on points.
int computeDiameterStats(const SimplexId nPoints, std::array< double *const, 3 > diamStats, const std::vector< SimplexId > &connectivity, const std::vector< double > &cellDiameters) const
Compute diameter statistics on points.
int execute(std::vector< SimplexId > &connectivity, std::vector< double > &diameters, std::array< double *const, 3 > diamStats, const std::vector< std::vector< double > > &distanceMatrix, double *const density=nullptr) const
Main entry point.
int SimplexId
Identifier type for simplices of any dimension.
std::array< ttk::SimplexId, n > verts
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)