282 dataType *
const scalars,
SimplexId *
const offsets)
const {
285 if(std::is_same<dataType, double>::value)
286 epsilon = Geometry::powIntTen<dataType>(1 - DBL_DIG);
287 else if(std::is_same<dataType, float>::value)
288 epsilon = Geometry::powIntTen<dataType>(1 - FLT_DIG);
292 std::vector<std::tuple<dataType, SimplexId, SimplexId>> perturbation(
294 for(
SimplexId i = 0; i < vertexNumber_; ++i) {
295 std::get<0>(perturbation[i]) = scalars[i];
296 std::get<1>(perturbation[i]) = offsets[i];
297 std::get<2>(perturbation[i]) = i;
301 sort(perturbation.begin(), perturbation.end(), cmp);
303 for(
SimplexId i = 0; i < vertexNumber_; ++i) {
305 if(std::get<0>(perturbation[i]) <= std::get<0>(perturbation[i - 1]))
306 std::get<0>(perturbation[i])
307 = std::get<0>(perturbation[i - 1]) + epsilon;
309 scalars[std::get<2>(perturbation[i])] = std::get<0>(perturbation[i]);
317 const dataType *
const inputScalars,
318 dataType *
const outputScalars,
323 const triangulationType &triangulation)
const {
328#ifdef TTK_ENABLE_OPENMP
329#pragma omp parallel for num_threads(threadNumber_)
331 for(
SimplexId k = 0; k < vertexNumber_; ++k) {
332 outputScalars[k] = inputScalars[k];
333 if(std::isnan((
double)outputScalars[k]))
334 outputScalars[k] = 0;
336 offsets[k] = inputOffsets[k];
340 std::vector<bool> extrema(vertexNumber_,
false);
341 for(
SimplexId k = 0; k < constraintNumber; ++k) {
342 const SimplexId identifierId = identifiers[k];
344#ifndef TTK_ENABLE_KAMIKAZE
345 if(identifierId >= 0 and identifierId < vertexNumber_)
347 extrema[identifierId] =
true;
350 std::vector<SimplexId> authorizedMinima;
351 std::vector<SimplexId> authorizedMaxima;
352 std::vector<bool> authorizedExtrema(vertexNumber_,
false);
355 offsets, authorizedMinima, authorizedMaxima, extrema, triangulation);
357 this->
printMsg(
"Maintaining " + std::to_string(constraintNumber)
358 +
" constraints (" + std::to_string(authorizedMinima.size())
359 +
" minima and " + std::to_string(authorizedMaxima.size())
367 for(
SimplexId i = 0; i < vertexNumber_; ++i) {
369 this->
printMsg(
"Starting simplifying iteration #" + std::to_string(i),
372 for(
int j = 0; j < 2; ++j) {
374 bool const isIncreasingOrder = !j;
376 if(isIncreasingOrder && authorizedMinima.empty()) {
379 if(!isIncreasingOrder && authorizedMaxima.empty()) {
384 std::set<std::tuple<dataType, SimplexId, SimplexId>,
decltype(cmp)>
386 std::vector<bool> visitedVertices(vertexNumber_,
false);
387 std::vector<SimplexId> adjustmentSequence(vertexNumber_);
390 if(isIncreasingOrder) {
391 for(
SimplexId const k : authorizedMinima) {
392 authorizedExtrema[k] =
true;
393 sweepFront.emplace(outputScalars[k], offsets[k], k);
394 visitedVertices[k] =
true;
397 for(
SimplexId const k : authorizedMaxima) {
398 authorizedExtrema[k] =
true;
399 sweepFront.emplace(outputScalars[k], offsets[k], k);
400 visitedVertices[k] =
true;
407 auto front = sweepFront.begin();
408 if(front == sweepFront.end())
411 SimplexId const vertexId = std::get<2>(*front);
412 sweepFront.erase(front);
415 = triangulation.getVertexNeighborNumber(vertexId);
416 for(
SimplexId k = 0; k < neighborNumber; ++k) {
418 triangulation.getVertexNeighbor(vertexId, k, neighbor);
419 if(!visitedVertices[neighbor]) {
421 outputScalars[neighbor], offsets[neighbor], neighbor);
422 visitedVertices[neighbor] =
true;
425 adjustmentSequence[adjustmentPos] = vertexId;
427 }
while(!sweepFront.empty());
430 SimplexId offset = (isIncreasingOrder ? 0 : vertexNumber_);
432 for(
SimplexId k = 0; k < vertexNumber_; ++k) {
434 if(isIncreasingOrder) {
436 && outputScalars[adjustmentSequence[k]]
437 <= outputScalars[adjustmentSequence[k - 1]])
438 outputScalars[adjustmentSequence[k]]
439 = outputScalars[adjustmentSequence[k - 1]];
443 && outputScalars[adjustmentSequence[k]]
444 >= outputScalars[adjustmentSequence[k - 1]])
445 outputScalars[adjustmentSequence[k]]
446 = outputScalars[adjustmentSequence[k - 1]];
449 offsets[adjustmentSequence[k]] = offset;
454 bool needForMoreIterations{
false};
455 std::vector<SimplexId> minima;
456 std::vector<SimplexId> maxima;
457 getCriticalPoints(offsets, minima, maxima, triangulation);
459 if(maxima.size() > authorizedMaxima.size())
460 needForMoreIterations =
true;
461 if(minima.size() > authorizedMinima.size())
462 needForMoreIterations =
true;
465 std::vector<std::vector<std::string>>{
466 {
"#Minima", std::to_string(minima.size())},
467 {
"#Maxima", std::to_string(maxima.size())},
471 if(!needForMoreIterations) {
473 if(!authorizedExtrema[k]) {
474 needForMoreIterations =
true;
479 if(!needForMoreIterations) {
481 if(!authorizedExtrema[k]) {
482 needForMoreIterations =
true;
490 addPerturbation<dataType>(outputScalars, offsets);
492 if(!needForMoreIterations)
497 "Simplified scalar field", 1.0, t.
getElapsedTime(), this->threadNumber_);