59 template <
class triangulationType = AbstractTriangulation>
85 template <
class scalarT>
92 template <
class triangulationType = AbstractTriangulation>
97 template <
class triangulationType = AbstractTriangulation>
100 template <
typename scalarT,
class triangulationType = AbstractTriangulation>
108 template <
typename scalarT,
class triangulationType = AbstractTriangulation>
115 template <
typename scalarT,
class triangulationType = AbstractTriangulation>
116 void extendOutPts(
const std::vector<SimplexId> &vertices,
122 template <
class triangulationType = AbstractTriangulation>
125 float x = 0, y = 0, z = 0;
128 _radius = std::sqrt(x * x + y * y + z * z);
130 _radius = std::numeric_limits<double>::signaling_NaN();
171 template <
class Po
intIterable,
class WeightIterable>
173 array<double, std::tuple_size<typename PointIterable::value_type>::value>
174 average(
const PointIterable &pts,
const WeightIterable &ws);
225 _outContoursCinfos.resize(0);
227 _outContoursCoords.resize(0);
228 _outContoursScalars.resize(0);
229 _outContoursFlags.resize(0);
231 _outCentroidsCoords.resize(0);
232 _outCentroidsScalars.resize(0);
233 _outCentroidsFlags.resize(0);
235#ifndef TTK_ENABLE_KAMIKAZE
257 for(
size_t p = 0; p < _inpPtsNum; ++p) {
258 handleOneInpPt<scalarT>(
259 findInpFldVert(p), _inpPtsIsovals[p], _inpPtsFlags[p], _inpPtsScalars[p]);
303 float scalar)
const {
304 auto triang =
reinterpret_cast<Triang *
>(_inpFldTriang);
305 auto inpScalars =
reinterpret_cast<const scalarT *
>(_inpFldScalars);
306 const bool vBegIsMin = flag == 0;
315 auto innerVerts = std::vector<SimplexId>{vBeg};
316 std::set<SimplexId> xEdges;
322 std::vector<VertEdge> q;
323 std::set<SimplexId> handledEdges;
325 auto enqueueNeighbors = [triang, &q, &handledEdges](
SimplexId vSrc) {
326 const auto n = triang->getVertexEdgeNumber(vSrc);
329 triang->getVertexEdge(vSrc, i, e);
330 if(handledEdges.count(e))
332 handledEdges.insert(e);
336 triang->getVertexNeighbor(vSrc, i, vTgt);
337 q.push_back({vTgt, e});
341 enqueueNeighbors(vBeg);
343 const auto ve = q.back();
346 const bool vIsAboveIso = inpScalars[v] > isoval;
347 if(vBegIsMin == vIsAboveIso) {
350 innerVerts.push_back(v);
355 if(innerVerts.size() < _sizeMin)
357 extendOutFld<scalarT>(xEdges, isoval, flag);
358 extendOutPts<scalarT>(innerVerts, isoval, flag, scalar);
366 auto triang =
reinterpret_cast<Triang *
>(_inpFldTriang);
367 auto inpScalars =
reinterpret_cast<const scalarT *
>(_inpFldScalars);
376 std::map<SimplexId, SimplexId> inpe2outv;
378 auto getOrMakeOutVert = [&](
SimplexId e) {
379 if(inpe2outv.count(e))
383 const SimplexId v = _outContoursScalars.size();
387 triang->getEdgeVertex(e, 0, p);
389 triang->getEdgeVertex(e, 1, q);
391 const float pVal =
static_cast<float>(inpScalars[p]);
392 const float qVal =
static_cast<float>(inpScalars[q]);
393 const double pFac = (qVal - isoval) / (qVal - pVal);
394 const double qFac = 1 - pFac;
397 triang->getVertexPoint(p, px, py, pz);
399 triang->getVertexPoint(q, qx, qy, qz);
400 const float x = px * pFac + qx * qFac;
401 const float y = py * pFac + qy * qFac;
402 const float z = pz * pFac + qz * qFac;
403 _outContoursCoords.push_back(x);
404 _outContoursCoords.push_back(y);
405 _outContoursCoords.push_back(z);
407 _outContoursScalars.push_back(isoval);
408 _outContoursFlags.push_back(flag);
413 std::set<SimplexId> handledTris;
416 printWrn(
"Currently only the *edges* of contour surfaces are computed");
418 for(
const auto e : inpEdges) {
419 const auto nTriLoc = triang->getEdgeTriangleNumber(e);
423 const auto v = getOrMakeOutVert(e);
425 for(
SimplexId tLoc = 0; tLoc < nTriLoc; ++tLoc) {
427 triang->getEdgeTriangle(e, tLoc, tGlo);
428 if(handledTris.count(tGlo))
431 handledTris.insert(tGlo);
433 for(
SimplexId eLoc = 0; eLoc < 3; ++eLoc) {
435 triang->getTriangleEdge(tGlo, eLoc, eGlo);
436 if(eGlo == e || !inpEdges.count(eGlo))
440 _outContoursCinfos.push_back(2);
441 _outContoursCinfos.push_back(v);
442 _outContoursCinfos.push_back(getOrMakeOutVert(eGlo));
452 const std::vector<SimplexId> &vertices,
455 float extremeVal)
const {
457 auto triang =
reinterpret_cast<Triang *
>(_inpFldTriang);
458 auto inpScalars =
reinterpret_cast<const scalarT *
>(_inpFldScalars);
460 const double radius = _radius;
461 const bool spherical = radius > 0.;
466 const double scalarDiffMax = std::abs(isoval - extremeVal);
469 const double kernelInputScaler =
M_PI / scalarDiffMax;
471 auto scalar_w = [kernelInputScaler](
double d) {
472 return (std::cos(d * kernelInputScaler) + 1.) / 2.;
479 const bool regularLonLat = spherical;
483 const auto numVerts = vertices.size();
484 auto pts4d = std::vector<std::array<float, 4>>(numVerts);
485 auto ws = std::vector<double>(numVerts);
486 for(std::size_t i = 0; i < numVerts; ++i) {
488 const auto v = vertices[i];
489 const scalarT vSca = inpScalars[v];
492 const double scalarDiff = vSca - extremeVal;
493 const double scalarW = scalar_w(scalarDiff);
496 triang->getVertexPoint(v, x, y, z);
497 pts4d[i] = {x, y, z,
static_cast<float>(vSca)};
503 printWrn(
"Vertex weighting does not consider vertex density of this "
513 static const auto compDist
514 = [](
float ax,
float ay,
float az,
float bx,
float by,
float bz) {
515 const auto dx = bx - ax;
516 const auto dy = by - ay;
517 const auto dz = bz - az;
518 return std::sqrt(dx * dx + dy * dy + dz * dz);
523 static const auto compArea = [](
double a,
double b,
double c) {
524 const double s = (a + b + c) / 2.;
527 3 * s * s - s * a - s * b
534 float x2, y2, z2, x3, y3, z3;
536 triang->getVertexNeighbor(v, 0, u);
537 triang->getVertexPoint(u, x2, y2, z2);
538 double a = compDist(x, y, z, x2, y2, z2);
541 const float x2Bak = x2, y2Bak = y2, z2Bak = z2;
542 const double aBak = a;
544 const SimplexId n = triang->getVertexNeighborNumber(v);
546 triang->getVertexNeighbor(v, j, u);
547 triang->getVertexPoint(u, x3, y3, z3);
548 const double b = compDist(x, y, z, x3, y3, z3);
549 const double c = compDist(x2, y2, z2, x3, y3, z3);
550 area += compArea(a, b, c);
557 const double b = aBak;
558 const double c = compDist(x2, y2, z2, x2Bak, y2Bak, z2Bak);
559 area += compArea(a, b, c);
561 ws[i] = scalarW * area;
565 const double latInRad = std::asin(z / radius);
567 const double spatialW = std::cos(latInRad);
568 ws[i] = scalarW * spatialW;
576 const auto res = average(pts4d, ws);
582 const auto radiusCur = std::sqrt(x * x + y * y + z * z);
583 const auto radiusScaler = radius / radiusCur;
590 _outCentroidsCoords.push_back(
static_cast<float>(x));
591 _outCentroidsCoords.push_back(
static_cast<float>(y));
592 _outCentroidsCoords.push_back(
static_cast<float>(z));
593 _outCentroidsScalars.push_back(
static_cast<float>(res[3]));
594 _outCentroidsFlags.push_back(flag);