| 1507 | } |
| 1508 | |
| 1509 | vtkSmartPointer<vtkAbstractArray> vtkGenerateStatistics::CellToPointSamples( |
| 1510 | vtkSmartPointer<vtkAbstractArray> fullArray, vtkDataSet* data, |
| 1511 | const std::unordered_map<vtkIdType, vtkIdType>& subset, |
| 1512 | const PointsOfCellsWeightMap& cellsToPointsToWeights) |
| 1513 | { |
| 1514 | auto* cellArray = vtkDataArray::SafeDownCast(fullArray); |
| 1515 | if (!cellArray) |
| 1516 | { |
| 1517 | vtkErrorMacro("Converting " << fullArray->GetClassName() << " named \"" << fullArray->GetName() |
| 1518 | << "\" from " |
| 1519 | "cell-centered to point-centered is unsupported."); |
| 1520 | return nullptr; |
| 1521 | } |
| 1522 | vtkSmartPointer<vtkDataArray> result; |
| 1523 | result.TakeReference(cellArray->NewInstance()); |
| 1524 | result->SetNumberOfTuples( |
| 1525 | subset.empty() ? data->GetNumberOfPoints() : static_cast<vtkIdType>(subset.size())); |
| 1526 | result->FillComponent(0, 0.); |
| 1527 | result->SetName(cellArray->GetName()); |
| 1528 | // Create an array to hold the sum of the weights for each point. |
| 1529 | // This is used to normalize the output point values. |
| 1530 | vtkNew<vtkDoubleArray> weightSum; |
| 1531 | weightSum->SetName("weightSum"); |
| 1532 | weightSum->SetNumberOfTuples( |
| 1533 | subset.empty() ? data->GetNumberOfPoints() : static_cast<vtkIdType>(subset.size())); |
| 1534 | weightSum->FillComponent(0, 0.); |
| 1535 | double cellValue; |
| 1536 | double resultValue; |
| 1537 | double currentWeight; |
| 1538 | // Since cellsToPointsToWeights only contains entries for |
| 1539 | // points in the \a subset (if \a subset is non-empty) and |
| 1540 | // contains values for all points (if \a subset is empty), |
| 1541 | // we can just loop over cellsToPointsToWeights to splat |
| 1542 | // exactly what is needed. |
| 1543 | for (const auto& entry : cellsToPointsToWeights) |
| 1544 | { |
| 1545 | auto cellId = entry.first; |
| 1546 | cellArray->GetTuple(cellId, &cellValue); |
| 1547 | for (const auto& pointToWeight : entry.second) |
| 1548 | { |
| 1549 | result->GetTuple(pointToWeight.first, &resultValue); |
| 1550 | resultValue += pointToWeight.second * cellValue; |
| 1551 | result->SetTuple(pointToWeight.first, &resultValue); |
| 1552 | weightSum->GetTuple(pointToWeight.first, ¤tWeight); |
| 1553 | currentWeight += pointToWeight.second; |
| 1554 | weightSum->SetTuple(pointToWeight.first, ¤tWeight); |
| 1555 | } |
| 1556 | } |
| 1557 | // Now divide each point's value by its matching weightSum. |
| 1558 | // This also conveniently turns points with no contribution from any cell into NaN values |
| 1559 | // for us. In the future we might offer users an option to replace NaN values with some |
| 1560 | // meaningful constant on a per-array basis. |
| 1561 | vtkSMPTools::For(0, result->GetNumberOfTuples(), |
| 1562 | [&](vtkIdType begin, vtkIdType end) |
| 1563 | { |
| 1564 | double vv; |
| 1565 | double ww; |
| 1566 | for (vtkIdType ii = begin; ii < end; ++ii) |
no test coverage detected