99 const dataType1 *scalars1,
100 const dataType2 *scalars2,
101 const triangulationType *triangulation)
const {
102#ifndef TTK_ENABLE_KAMIKAZE
112 if(triangulation->getNumberOfCells() <= 0) {
117 if(triangulation->getCellVertexNumber(0) != 4) {
126 const SimplexId numberOfCells = triangulation->getNumberOfCells();
130 const double d[3]{0, 0, -1};
131 const double delta[2]{
133 const double sampling[2]{
135 const double epsilon{0.000001};
137 std::vector<std::array<SimplexId, 3>> triangles{};
139#ifdef TTK_ENABLE_OPENMP
140#pragma omp parallel for num_threads(threadNumber_) firstprivate(triangles)
142 for(
SimplexId cell = 0; cell < numberOfCells; ++cell) {
148 float position[4][3];
149 double localScalarMin[2]{};
150 double localScalarMax[2]{};
152 for(
int k = 0; k < 4; ++k) {
154 triangulation->getCellVertex(cell, k, vertex[k]);
157 data[k][0] = scalars1[vertex[k]];
158 data[k][1] = scalars2[vertex[k]];
168 if(!k or localScalarMin[0] > data[k][0])
169 localScalarMin[0] = data[k][0];
170 if(!k or localScalarMin[1] > data[k][1])
171 localScalarMin[1] = data[k][1];
172 if(!k or localScalarMax[0] < data[k][0])
173 localScalarMax[0] = data[k][0];
174 if(!k or localScalarMax[1] < data[k][1])
175 localScalarMax[1] = data[k][1];
178 triangulation->getVertexPoint(
179 vertex[k], position[k][0], position[k][1], position[k][2]);
194 for(
int k = 0; k < 3; ++k) {
195 v12[k] = position[1][k] - position[0][k];
196 v13[k] = position[2][k] - position[0][k];
197 v14[k] = position[3][k] - position[0][k];
199 s12[k] = data[1][k] - data[0][k];
200 s13[k] = data[2][k] - data[0][k];
201 s14[k] = data[3][k] - data[0][k];
212 for(
int k = 0; k < 3; ++k) {
217 const double invDet = 1.0 / det;
218 for(
int k = 0; k < 3; ++k) {
219 g0[k] = (s14[0] * a[k] + s13[0] * b[k] + s12[0] * c[k]) * invDet;
220 g1[k] = (s14[1] * a[k] + s13[1] * b[k] + s12[1] * c[k]) * invDet;
248 int index[4]{0, 1, 2, 3};
251 const bool zCrossProductsSigns[4]
252 = {(data[1][0] - data[0][0]) * (data[2][1] - data[0][1])
253 - (data[1][1] - data[0][1]) * (data[2][0] - data[0][0])
255 (data[2][0] - data[1][0]) * (data[3][1] - data[1][1])
256 - (data[2][1] - data[1][1]) * (data[3][0] - data[1][0])
258 (data[3][0] - data[2][0]) * (data[0][1] - data[2][1])
259 - (data[3][1] - data[2][1]) * (data[0][0] - data[2][0])
261 (data[0][0] - data[3][0]) * (data[1][1] - data[3][1])
262 - (data[0][1] - data[3][1]) * (data[1][0] - data[3][0])
268 if((zCrossProductsSigns[0] != zCrossProductsSigns[1])
269 != (zCrossProductsSigns[2] != zCrossProductsSigns[3])) {
271 if(zCrossProductsSigns[1] == zCrossProductsSigns[2]
272 && zCrossProductsSigns[2] == zCrossProductsSigns[3]) {
277 }
else if(zCrossProductsSigns[0] == zCrossProductsSigns[2]
278 && zCrossProductsSigns[2] == zCrossProductsSigns[3]) {
283 }
else if(zCrossProductsSigns[0] == zCrossProductsSigns[1]
284 && zCrossProductsSigns[1] == zCrossProductsSigns[2]) {
294 double imaginaryPosition[3]{0, 0, 0};
296 std::array<SimplexId, 3> triangle{};
301 double massDensity{};
306 data[index[0]], data[index[1]], data[index[2]], fullArea);
313 invArea = 1.0 / fullArea;
315 double alpha, beta, gamma;
317 data[index[1]], data[index[2]], data[index[3]], alpha);
320 data[index[0]], data[index[2]], data[index[3]], beta);
323 data[index[0]], data[index[1]], data[index[3]], gamma);
329 double centralPoint[3];
330 double interpolatedPoint[3];
333 for(
int k = 0; k < 3; ++k) {
334 centralPoint[k] = position[index[3]][k];
335 interpolatedPoint[k] = alpha * position[index[0]][k]
336 + beta * position[index[1]][k]
337 + gamma * position[index[2]][k];
343 density = std::numeric_limits<
decltype(density)>::max();
345 density = massDensity / volume;
347 triangle[0] = vertex[index[3]];
348 triangle[1] = vertex[index[0]];
349 triangle[2] = vertex[index[1]];
350 triangles.push_back(triangle);
352 triangle[0] = vertex[index[3]];
353 triangle[1] = vertex[index[0]];
354 triangle[2] = vertex[index[2]];
355 triangles.push_back(triangle);
357 triangle[0] = vertex[index[3]];
358 triangle[1] = vertex[index[1]];
359 triangle[2] = vertex[index[2]];
360 triangles.push_back(triangle);
364 double massDensity{};
370 if(zCrossProductsSigns[0] != zCrossProductsSigns[1]) {
376 data[0][0], data[0][1], data[3][0], data[3][1], data[1][0],
377 data[1][1], data[2][0], data[2][1], imaginaryPosition[0],
378 imaginaryPosition[1]);
379 }
else if(zCrossProductsSigns[2] != zCrossProductsSigns[1]) {
385 data[0][0], data[0][1], data[1][0], data[1][1], data[2][0],
386 data[2][1], data[3][0], data[3][1], imaginaryPosition[0],
387 imaginaryPosition[1]);
394 data[0][0], data[0][1], data[2][0], data[2][1], data[1][0],
395 data[1][1], data[3][0], data[3][1], imaginaryPosition[0],
396 imaginaryPosition[1]);
399 double distanceToIntersection
401 double diagonalLength
403 const double r0 = distanceToIntersection / diagonalLength;
405 distanceToIntersection
408 const double r1 = distanceToIntersection / diagonalLength;
412 for(
int k = 0; k < 3; ++k) {
413 p0[k] = position[index[0]][k]
414 + r0 * (position[index[1]][k] - position[index[0]][k]);
416 p1[k] = position[index[2]][k]
417 + r1 * (position[index[3]][k] - position[index[2]][k]);
422 density = std::numeric_limits<
decltype(density)>::max();
424 density = massDensity / volume;
428 triangle[1] = vertex[index[0]];
429 triangle[2] = vertex[index[2]];
430 triangles.push_back(triangle);
432 triangle[1] = vertex[index[2]];
433 triangle[2] = vertex[index[1]];
434 triangles.push_back(triangle);
436 triangle[1] = vertex[index[1]];
437 triangle[2] = vertex[index[3]];
438 triangles.push_back(triangle);
440 triangle[1] = vertex[index[3]];
441 triangle[2] = vertex[index[0]];
442 triangles.push_back(triangle);
450 = floor((localScalarMin[0] -
scalarMin_[0]) / sampling[0]);
452 = floor((localScalarMin[1] -
scalarMin_[1]) / sampling[1]);
454 = ceil((localScalarMax[0] -
scalarMin_[0]) / sampling[0]);
456 = ceil((localScalarMax[1] -
scalarMin_[1]) / sampling[1]);
461 const double o[3]{
scalarMin_[0] + i * sampling[0],
463 for(
unsigned int k = 0; k < triangles.size(); ++k) {
464 const auto &tr = triangles[k];
469 p0[0] = scalars1[tr[0]];
470 p0[1] = scalars2[tr[0]];
472 p0[0] = imaginaryPosition[0];
473 p0[1] = imaginaryPosition[1];
478 (double)scalars1[tr[1]], (
double)scalars2[tr[1]], 0};
480 (double)scalars1[tr[2]], (
double)scalars2[tr[2]], 0};
481 const double e1[3]{p1[0] - p0[0], p1[1] - p0[1], 0};
482 const double e2[3]{p2[0] - p0[0], p2[1] - p0[1], 0};
487 if(a > -epsilon and a < epsilon)
490 const double f = 1.0 / a;
491 const double s[3]{o[0] - p0[0], o[1] - p0[1], 1};
499 if(v < 0.0 or (u + v) > 1.0)
503#ifdef TTK_ENABLE_OPENMP
504#pragma omp atomic update
506 (*density_)[i][j] += (1.0 - u - v) * density;
508#ifdef TTK_ENABLE_OPENMP
509#pragma omp atomic write
511 (*validPointMask_)[i][j] = 1;
520 std::stringstream msg;
521 msg <<
"Processed " << numberOfCells <<
" tetrahedra";