// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkIntegrationLinearStrategy.h" #include "vtkCellData.h" #include "vtkCellTypeUtilities.h" #include "vtkDataArray.h" #include "vtkDataSet.h" #include "vtkDoubleArray.h" #include "vtkIntegrateAttributes.h" #include "vtkIntegrateAttributesFieldList.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkUnstructuredGrid.h" VTK_ABI_NAMESPACE_BEGIN //------------------------------------------------------------------------------ vtkStandardNewMacro(vtkIntegrationLinearStrategy); //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Integration Strategy: Linear" << std::endl; } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegratePolyLine(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { double length; double pt1[3], pt2[3], mid[3]; vtkIdType numLines, lineIdx; vtkIdType pt1Id, pt2Id; numLines = numPts - 1; for (lineIdx = 0; lineIdx < numLines; ++lineIdx) { pt1Id = cellPtIds[lineIdx]; pt2Id = cellPtIds[lineIdx + 1]; input->GetPoint(pt1Id, pt1); input->GetPoint(pt2Id, pt2); // Compute the length of the line. length = std::sqrt(vtkMath::Distance2BetweenPoints(pt1, pt2)); sum += length; // Compute the middle, which is really just another attribute. mid[0] = (pt1[0] + pt2[0]) * 0.5; mid[1] = (pt1[1] + pt2[1]) * 0.5; mid[2] = (pt1[2] + pt2[2]) * 0.5; // Add weighted to sumCenter. sumCenter[0] += mid[0] * length; sumCenter[1] += mid[1] * length; sumCenter[2] += mid[2] * length; // Now integrate the rest of the attributes. this->IntegrateData2( input->GetPointData(), output->GetPointData(), pt1Id, pt2Id, length, pointFieldList, index); this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, length, cellFieldList, index); } } //------------------------------------------------------------------------------ // Works for convex polygons, and interpolation is not correct. void vtkIntegrationLinearStrategy::IntegratePolygon(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { vtkIdType numTris, triIdx; vtkIdType pt1Id, pt2Id, pt3Id; numTris = numPts - 2; pt1Id = cellPtIds[0]; for (triIdx = 0; triIdx < numTris; ++triIdx) { pt2Id = cellPtIds[triIdx + 1]; pt3Id = cellPtIds[triIdx + 2]; this->IntegrateTriangle(input, output, cellId, pt1Id, pt2Id, pt3Id, sum, sumCenter, cellFieldList, pointFieldList, index); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateTriangleStrip(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { vtkIdType numTris, triIdx; vtkIdType pt1Id, pt2Id, pt3Id; numTris = numPts - 2; for (triIdx = 0; triIdx < numTris; ++triIdx) { pt1Id = cellPtIds[triIdx]; pt2Id = cellPtIds[triIdx + 1]; pt3Id = cellPtIds[triIdx + 2]; this->IntegrateTriangle(input, output, cellId, pt1Id, pt2Id, pt3Id, sum, sumCenter, cellFieldList, pointFieldList, index); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateTriangle(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType pt1Id, vtkIdType pt2Id, vtkIdType pt3Id, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { double pt1[3], pt2[3], pt3[3]; double mid[3], v1[3], v2[3]; double cross[3]; double area; input->GetPoint(pt1Id, pt1); input->GetPoint(pt2Id, pt2); input->GetPoint(pt3Id, pt3); // Compute two legs. v1[0] = pt2[0] - pt1[0]; v1[1] = pt2[1] - pt1[1]; v1[2] = pt2[2] - pt1[2]; v2[0] = pt3[0] - pt1[0]; v2[1] = pt3[1] - pt1[1]; v2[2] = pt3[2] - pt1[2]; // Use the cross product to compute the area of the parallelogram. vtkMath::Cross(v1, v2, cross); area = std::sqrt(cross[0] * cross[0] + cross[1] * cross[1] + cross[2] * cross[2]) * 0.5; if (area == 0.0) { return; } sum += area; // Compute the middle, which is really just another attribute. mid[0] = (pt1[0] + pt2[0] + pt3[0]) / 3.0; mid[1] = (pt1[1] + pt2[1] + pt3[1]) / 3.0; mid[2] = (pt1[2] + pt2[2] + pt3[2]) / 3.0; // Add weighted to sumCenter. sumCenter[0] += mid[0] * area; sumCenter[1] += mid[1] * area; sumCenter[2] += mid[2] * area; // Now integrate the rest of the attributes. this->IntegrateData3(input->GetPointData(), output->GetPointData(), pt1Id, pt2Id, pt3Id, area, pointFieldList, index); this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, area, cellFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateQuad(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType pt1Id, vtkIdType pt2Id, vtkIdType pt3Id, vtkIdType pt4Id, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { this->IntegrateTriangle(input, output, cellId, pt1Id, pt2Id, pt3Id, sum, sumCenter, cellFieldList, pointFieldList, index); this->IntegrateTriangle(input, output, cellId, pt1Id, pt4Id, pt3Id, sum, sumCenter, cellFieldList, pointFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateTetrahedron(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType pt1Id, vtkIdType pt2Id, vtkIdType pt3Id, vtkIdType pt4Id, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { double pts[4][3]; input->GetPoint(pt1Id, pts[0]); input->GetPoint(pt2Id, pts[1]); input->GetPoint(pt3Id, pts[2]); input->GetPoint(pt4Id, pts[3]); double edge0[3], edge1[3], edge2[3], normal[3], volume, mid[3]; // Compute the principle vectors around pt0 and the // centroid for (int i = 0; i < 3; i++) { edge0[i] = pts[1][i] - pts[0][i]; edge1[i] = pts[2][i] - pts[0][i]; edge2[i] = pts[3][i] - pts[0][i]; mid[i] = (pts[0][i] + pts[1][i] + pts[2][i] + pts[3][i]) * 0.25; } // Calculate the volume of the tet which is 1/6 * the box product vtkMath::Cross(edge0, edge1, normal); volume = vtkMath::Dot(edge2, normal) / 6.0; sum += volume; // Add weighted to sumCenter. sumCenter[0] += mid[0] * volume; sumCenter[1] += mid[1] * volume; sumCenter[2] += mid[2] * volume; // Integrate the attributes on the cell itself this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, volume, cellFieldList, index); // Integrate the attributes associated with the points this->IntegrateData4(input->GetPointData(), output->GetPointData(), pt1Id, pt2Id, pt3Id, pt4Id, volume, pointFieldList, index); } //------------------------------------------------------------------------------ // For axis aligned rectangular cells void vtkIntegrationLinearStrategy::IntegratePixel(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType vtkNotUsed(numPts), const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { double pts[4][3]; input->GetPoint(cellPtIds[0], pts[0]); input->GetPoint(cellPtIds[1], pts[1]); input->GetPoint(cellPtIds[2], pts[2]); input->GetPoint(cellPtIds[3], pts[3]); double length, width, area, mid[3]; // get the lengths of its 2 orthogonal sides. Since only 1 coordinate // can be different we can add the differences in all 3 directions length = (pts[0][0] - pts[1][0]) + (pts[0][1] - pts[1][1]) + (pts[0][2] - pts[1][2]); width = (pts[0][0] - pts[2][0]) + (pts[0][1] - pts[2][1]) + (pts[0][2] - pts[2][2]); area = std::abs(length * width); sum += area; // Compute the middle, which is really just another attribute. mid[0] = (pts[0][0] + pts[1][0] + pts[2][0] + pts[3][0]) * 0.25; mid[1] = (pts[0][1] + pts[1][1] + pts[2][1] + pts[3][1]) * 0.25; mid[2] = (pts[0][2] + pts[1][2] + pts[2][2] + pts[3][2]) * 0.25; // Add weighted to sumCenter. sumCenter[0] += mid[0] * area; sumCenter[1] += mid[1] * area; sumCenter[2] += mid[2] * area; // Now integrate the rest of the attributes. this->IntegrateData4(input->GetPointData(), output->GetPointData(), cellPtIds[0], cellPtIds[1], cellPtIds[2], cellPtIds[3], area, pointFieldList, index); this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, area, cellFieldList, index); } //------------------------------------------------------------------------------ // For axis aligned hexahedral cells void vtkIntegrationLinearStrategy::IntegrateVoxel(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType vtkNotUsed(numPts), const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { vtkIdType pt1Id, pt2Id, pt3Id, pt4Id, pt5Id; double pts[5][3]; pt1Id = cellPtIds[0]; pt2Id = cellPtIds[1]; pt3Id = cellPtIds[2]; pt4Id = cellPtIds[3]; pt5Id = cellPtIds[4]; input->GetPoint(pt1Id, pts[0]); input->GetPoint(pt2Id, pts[1]); input->GetPoint(pt3Id, pts[2]); input->GetPoint(pt4Id, pts[3]); input->GetPoint(pt5Id, pts[4]); double length, width, height, volume, mid[3]; // Calculate the volume of the voxel length = pts[1][0] - pts[0][0]; width = pts[2][1] - pts[0][1]; height = pts[4][2] - pts[0][2]; volume = std::abs(length * width * height); sum += volume; // Partially Compute the middle, which is really just another attribute. mid[0] = (pts[0][0] + pts[1][0] + pts[2][0] + pts[3][0]) * 0.125; mid[1] = (pts[0][1] + pts[1][1] + pts[2][1] + pts[3][1]) * 0.125; mid[2] = (pts[0][2] + pts[1][2] + pts[2][2] + pts[3][2]) * 0.125; // Integrate the attributes on the cell itself this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, volume, cellFieldList, index); // Integrate the attributes associated with the points on the bottom face // note that since IntegrateData4 is going to weigh everything by 1/4 // we need to pass down 1/2 the volume so they will be weighted by 1/8 this->IntegrateData4(input->GetPointData(), output->GetPointData(), pt1Id, pt2Id, pt3Id, pt4Id, volume * 0.5, pointFieldList, index); // Now process the top face points pt1Id = cellPtIds[5]; pt2Id = cellPtIds[6]; pt3Id = cellPtIds[7]; input->GetPoint(pt1Id, pts[0]); input->GetPoint(pt2Id, pts[1]); input->GetPoint(pt3Id, pts[2]); // Finish Computing the middle, which is really just another attribute. mid[0] += (pts[0][0] + pts[1][0] + pts[2][0] + pts[4][0]) * 0.125; mid[1] += (pts[0][1] + pts[1][1] + pts[2][1] + pts[4][1]) * 0.125; mid[2] += (pts[0][2] + pts[1][2] + pts[2][2] + pts[4][2]) * 0.125; // Add weighted to sumCenter. sumCenter[0] += mid[0] * volume; sumCenter[1] += mid[1] * volume; sumCenter[2] += mid[2] * volume; // Integrate the attributes associated with the points on the top face // note that since IntegrateData4 is going to weigh everything by 1/4 // we need to pass down 1/2 the volume so they will be weighted by 1/8 this->IntegrateData4(input->GetPointData(), output->GetPointData(), pt1Id, pt2Id, pt3Id, pt5Id, volume * 0.5, pointFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateHexahedron(vtkDataSet* input, vtkUnstructuredGrid* output, vtkGenericCell* cell, vtkIdType cellId, vtkIdType numPts, const vtkIdType* vtkNotUsed(cellPtIds), vtkIdList* cellPtIdsList, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { this->IntegrateDefault(input, output, cell, cellId, numPts, cellPtIdsList, sum, sumCenter, cellFieldList, pointFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateWedge(vtkDataSet* input, vtkUnstructuredGrid* output, vtkGenericCell* cell, vtkIdType cellId, vtkIdType numPts, const vtkIdType* vtkNotUsed(cellPtIds), vtkIdList* cellPtIdsList, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { this->IntegrateDefault(input, output, cell, cellId, numPts, cellPtIdsList, sum, sumCenter, cellFieldList, pointFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegratePyramid(vtkDataSet* input, vtkUnstructuredGrid* output, vtkGenericCell* cell, vtkIdType cellId, vtkIdType numPts, const vtkIdType* vtkNotUsed(cellPtIds), vtkIdList* cellPtIdsList, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { this->IntegrateDefault(input, output, cell, cellId, numPts, cellPtIdsList, sum, sumCenter, cellFieldList, pointFieldList, index); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateGeneral1DCell(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { if (numPts % 2) { vtkWarningMacro("Odd number of points(" << numPts << ") encountered - skipping " << " 1D Cell: " << cellId); return; } double length; double pt1[3], pt2[3], mid[3]; for (vtkIdType pid = 0; pid < numPts; pid += 2) { input->GetPoint(cellPtIds[pid], pt1); input->GetPoint(cellPtIds[pid + 1], pt2); // Compute the length of the line. length = std::sqrt(vtkMath::Distance2BetweenPoints(pt1, pt2)); sum += length; // Compute the middle, which is really just another attribute. mid[0] = (pt1[0] + pt2[0]) * 0.5; mid[1] = (pt1[1] + pt2[1]) * 0.5; mid[2] = (pt1[2] + pt2[2]) * 0.5; // Add weighted to sumCenter. sumCenter[0] += mid[0] * length; sumCenter[1] += mid[1] * length; sumCenter[2] += mid[2] * length; // Now integrate the rest of the attributes. this->IntegrateData2(input->GetPointData(), output->GetPointData(), cellPtIds[pid], cellPtIds[pid + 1], length, pointFieldList, index); this->IntegrateData1( input->GetCellData(), output->GetCellData(), cellId, length, cellFieldList, index); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateGeneral2DCell(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { if (numPts % 3) { vtkWarningMacro("Number of points (" << numPts << ") is not divisible by 3 - skipping " << " 2D Cell: " << cellId); return; } vtkIdType pt1Id, pt2Id, pt3Id; for (vtkIdType triIdx = 0; triIdx < numPts;) { pt1Id = cellPtIds[triIdx++]; pt2Id = cellPtIds[triIdx++]; pt3Id = cellPtIds[triIdx++]; this->IntegrateTriangle(input, output, cellId, pt1Id, pt2Id, pt3Id, sum, sumCenter, cellFieldList, pointFieldList, index); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateGeneral3DCell(vtkDataSet* input, vtkUnstructuredGrid* output, vtkIdType cellId, vtkIdType numPts, const vtkIdType* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { if (numPts % 4) { vtkWarningMacro("Number of points (" << numPts << ") is not divisiable by 4 - skipping " << " 3D Cell: " << cellId); return; } vtkIdType pt1Id, pt2Id, pt3Id, pt4Id; for (vtkIdType tetIdx = 0; tetIdx < numPts;) { pt1Id = cellPtIds[tetIdx++]; pt2Id = cellPtIds[tetIdx++]; pt3Id = cellPtIds[tetIdx++]; pt4Id = cellPtIds[tetIdx++]; this->IntegrateTetrahedron(input, output, cellId, pt1Id, pt2Id, pt3Id, pt4Id, sum, sumCenter, cellFieldList, pointFieldList, index); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateDefault(vtkDataSet* input, vtkUnstructuredGrid* output, vtkGenericCell* cell, vtkIdType cellId, vtkIdType numPts, vtkIdList* cellPtIds, double& sum, double sumCenter[3], vtkIntegrateAttributesFieldList& cellFieldList, vtkIntegrateAttributesFieldList& pointFieldList, int index) { // We need to explicitly get the cell input->GetCell(cellId, cell); cell->TriangulateIds(1, cellPtIds); int cellType = input->GetCellType(cellId); int cellDim = vtkCellTypeUtilities::GetDimension(cellType); switch (cellDim) { case 1: this->IntegrateGeneral1DCell(input, output, cellId, numPts, cellPtIds->GetPointer(0), sum, sumCenter, cellFieldList, pointFieldList, index); break; case 2: this->IntegrateGeneral2DCell(input, output, cellId, cellPtIds->GetNumberOfIds(), cellPtIds->GetPointer(0), sum, sumCenter, cellFieldList, pointFieldList, index); break; case 3: this->IntegrateGeneral3DCell(input, output, cellId, cellPtIds->GetNumberOfIds(), cellPtIds->GetPointer(0), sum, sumCenter, cellFieldList, pointFieldList, index); break; default: vtkWarningMacro("Unsupported Cell Dimension = " << cellDim); } } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateData1(vtkDataSetAttributes* inda, vtkDataSetAttributes* outda, vtkIdType pt1Id, double volume, vtkIntegrateAttributesFieldList& fieldList, int index) { auto f = [pt1Id, volume](vtkAbstractArray* ainArray, vtkAbstractArray* aoutArray) { vtkDataArray* inArray = vtkDataArray::FastDownCast(ainArray); vtkDoubleArray* outArray = vtkDoubleArray::FastDownCast(aoutArray); if (inArray && outArray) { // We could template for speed. const int numComponents = inArray->GetNumberOfComponents(); for (int j = 0; j < numComponents; ++j) { const double vIn1 = inArray->GetComponent(pt1Id, j); const double dv = vIn1; const double vOut = (dv * volume) + outArray->GetTypedComponent(0, j); outArray->SetTypedComponent(0, j, vOut); } } }; fieldList.TransformData(index, inda, outda, f); } //------------------------------------------------------------------------------ void vtkIntegrationLinearStrategy::IntegrateData2(vtkDataSetAttributes* inda, vtkDataSetAttributes* outda, vtkIdType pt1Id, vtkIdType pt2Id, double volume, vtkIntegrateAttributesFieldList& fieldList, int index) { auto f = [pt1Id, pt2Id, volume](vtkAbstractArray* ainArray, vtkAbstractArray* aoutArray) { vtkDataArray* inArray = vtkDataArray::FastDownCast(ainArray); vtkDoubleArray* outArray = vtkDoubleArray::FastDownCast(aoutArray); if (inArray && outArray) { // We could template for speed. const int numComponents = inArray->GetNumberOfComponents(); for (int j = 0; j < numComponents; ++j) { const double vIn1 = inArray->GetComponent(pt1Id, j); const double vIn2 = inArray->GetComponent(pt2Id, j); const double dv = 0.5 * (vIn1 + vIn2); const double vOut = (dv * volume) + outArray->GetTypedComponent(0, j); outArray->SetTypedComponent(0, j, vOut); } } }; fieldList.TransformData(index, inda, outda, f); } //------------------------------------------------------------------------------ // Is the extra performance worth duplicating this code with IntergrateData2. void vtkIntegrationLinearStrategy::IntegrateData3(vtkDataSetAttributes* inda, vtkDataSetAttributes* outda, vtkIdType pt1Id, vtkIdType pt2Id, vtkIdType pt3Id, double volume, vtkIntegrateAttributesFieldList& fieldList, int index) { auto f = [pt1Id, pt2Id, pt3Id, volume](vtkAbstractArray* ainArray, vtkAbstractArray* aoutArray) { vtkDataArray* inArray = vtkDataArray::FastDownCast(ainArray); vtkDoubleArray* outArray = vtkDoubleArray::FastDownCast(aoutArray); if (inArray && outArray) { // We could template for speed. const int numComponents = inArray->GetNumberOfComponents(); for (int j = 0; j < numComponents; ++j) { const double vIn1 = inArray->GetComponent(pt1Id, j); const double vIn2 = inArray->GetComponent(pt2Id, j); const double vIn3 = inArray->GetComponent(pt3Id, j); const double dv = (vIn1 + vIn2 + vIn3) / 3.0; const double vOut = (dv * volume) + outArray->GetTypedComponent(0, j); outArray->SetTypedComponent(0, j, vOut); } } }; fieldList.TransformData(index, inda, outda, f); } //------------------------------------------------------------------------------ // Is the extra performance worth duplicating this code with IntergrateData2. void vtkIntegrationLinearStrategy::IntegrateData4(vtkDataSetAttributes* inda, vtkDataSetAttributes* outda, vtkIdType pt1Id, vtkIdType pt2Id, vtkIdType pt3Id, vtkIdType pt4Id, double volume, vtkIntegrateAttributesFieldList& fieldList, int index) { auto f = [pt1Id, pt2Id, pt3Id, pt4Id, volume]( vtkAbstractArray* ainArray, vtkAbstractArray* aoutArray) { vtkDataArray* inArray = vtkDataArray::FastDownCast(ainArray); vtkDoubleArray* outArray = vtkDoubleArray::FastDownCast(aoutArray); if (inArray && outArray) { // We could template for speed. const int numComponents = inArray->GetNumberOfComponents(); for (int j = 0; j < numComponents; ++j) { const double vIn1 = inArray->GetComponent(pt1Id, j); const double vIn2 = inArray->GetComponent(pt2Id, j); const double vIn3 = inArray->GetComponent(pt3Id, j); const double vIn4 = inArray->GetComponent(pt4Id, j); const double dv = (vIn1 + vIn2 + vIn3 + vIn4) * 0.25; const double vOut = (dv * volume) + outArray->GetTypedComponent(0, j); outArray->SetTypedComponent(0, j, vOut); } } }; fieldList.TransformData(index, inda, outda, f); } VTK_ABI_NAMESPACE_END