From 462f800503df93910ce11e55eac17a4539c6e6a0 Mon Sep 17 00:00:00 2001 From: Mathieu Westphal <mathieu.westphal@kitware.com> Date: Wed, 19 Feb 2025 17:14:25 +0100 Subject: [PATCH] vtkProbeFilter: Add support for probing oriented images --- Filters/Core/vtkProbeFilter.cxx | 146 +++++++++++++++----------------- Filters/Core/vtkProbeFilter.h | 3 +- 2 files changed, 68 insertions(+), 81 deletions(-) diff --git a/Filters/Core/vtkProbeFilter.cxx b/Filters/Core/vtkProbeFilter.cxx index 2ca2135ff9f..3249c931fb6 100644 --- a/Filters/Core/vtkProbeFilter.cxx +++ b/Filters/Core/vtkProbeFilter.cxx @@ -755,53 +755,72 @@ void vtkProbeFilter::ProbeEmptyPoints( } //------------------------------------------------------------------------------ -static void GetPointIdsInRange(double rangeMin, double rangeMax, double start, double stepsize, - int numSteps, int& minid, int& maxid) +void vtkProbeFilter::ProbeImagePointsInCell(vtkGenericCell* cell, vtkIdType cellId, + vtkDataSet* source, int srcBlockId, vtkImageData* input, vtkPointData* outPD, char* maskArray, + double* wtsBuff) { - if (stepsize == 0) - { - minid = maxid = 0; - return; - } + vtkPointData* pd = source->GetPointData(); + // 1. get coordinates of sampling grids - minid = vtkMath::Ceil((rangeMin - start) / stepsize); - if (minid < 0) + // Recover cell bounds + double cellBounds[6]; + source->GetCellBounds(cellId, cellBounds); + vtkBoundingBox cellBB(cellBounds); + + // Recover input bounds, we already know they intersect, but reduce cellbounds + // to input bounds to ensure ComputeStructuredCoordinates works as expected on + // the edges of the input bounds + double inBounds[6]; + input->GetBounds(inBounds); + cellBB.IntersectBox(inBounds); + + // If ComputeTolerance is set, compute a tolerance proportional to the + // cell length. Otherwise, use the user specified absolute tolerance. + double tol2; + if (this->ComputeTolerance) { - minid = 0; + const vtkBoundingBox bbox(cellBounds); + tol2 = CELL_TOLERANCE_FACTOR_SQR * bbox.GetDiagonalLength2(); } - - maxid = vtkMath::Floor((rangeMax - start) / stepsize); - if (maxid > numSteps - 1) + else { - maxid = numSteps - 1; + tol2 = this->Tolerance * this->Tolerance; } -} -//------------------------------------------------------------------------------ -void vtkProbeFilter::ProbeImagePointsInCell(vtkGenericCell* cell, vtkIdType cellId, - vtkDataSet* source, int srcBlockId, const double start[3], const double spacing[3], - const int dim[3], vtkPointData* outPD, char* maskArray, double* wtsBuff) -{ - vtkPointData* pd = source->GetPointData(); - - // get coordinates of sampling grids - double cellBounds[6]; - source->GetCellBounds(cellId, cellBounds); + // Iterate on each point of the bounding box + // to identify the covered grid + int* inputExtent = input->GetExtent(); + int idxBounds[6] = { std::numeric_limits<int>::max(), std::numeric_limits<int>::min(), + std::numeric_limits<int>::max(), std::numeric_limits<int>::min(), + std::numeric_limits<int>::max(), std::numeric_limits<int>::min() }; + double corner[3]; + int ijk[3]; + double pCoords[3]; + bool found = false; + for (int i = 0; i < 8; i++) + { + cellBB.GetCorner(i, corner); + if (input->ComputeStructuredCoordinates(corner, ijk, pCoords, tol2)) + { + found = true; + for (int j = 0; j < 3; j++) + { + idxBounds[2 * j] = std::min(ijk[j], idxBounds[2 * j]); - int idxBounds[6]; - GetPointIdsInRange( - cellBounds[0], cellBounds[1], start[0], spacing[0], dim[0], idxBounds[0], idxBounds[1]); - GetPointIdsInRange( - cellBounds[2], cellBounds[3], start[1], spacing[1], dim[1], idxBounds[2], idxBounds[3]); - GetPointIdsInRange( - cellBounds[4], cellBounds[5], start[2], spacing[2], dim[2], idxBounds[4], idxBounds[5]); + // Force a +1 here to ensure we get even the edge of the input + // In some case that can be outside of the input image + int externalExtent = std::min(ijk[j] + 1, inputExtent[2 * j + 1]); + idxBounds[2 * j + 1] = std::max(externalExtent, idxBounds[2 * j + 1]); + } + } + } - if ((idxBounds[1] - idxBounds[0]) < 0 || (idxBounds[3] - idxBounds[2]) < 0 || - (idxBounds[5] - idxBounds[4]) < 0) + if (!found) { return; } + // 2. Recover the cell to process source->GetCell(cellId, cell); double cpbuf[3]; @@ -814,35 +833,23 @@ void vtkProbeFilter::ProbeImagePointsInCell(vtkGenericCell* cell, vtkIdType cell closestPoint = nullptr; } - // If ComputeTolerance is set, compute a tolerance proportional to the - // cell length. Otherwise, use the user specified absolute tolerance. - double tol2; - if (this->ComputeTolerance) + // 3. Check each indices from the grid + for (ijk[2] = idxBounds[4]; ijk[2] <= idxBounds[5]; ijk[2]++) { - const vtkBoundingBox bbox(cellBounds); - tol2 = CELL_TOLERANCE_FACTOR_SQR * bbox.GetDiagonalLength2(); - } - else - { - tol2 = this->Tolerance * this->Tolerance; - } - for (vtkIdType iz = idxBounds[4]; iz <= idxBounds[5]; iz++) - { - double p[3]; - p[2] = start[2] + iz * spacing[2]; - for (vtkIdType iy = idxBounds[2]; iy <= idxBounds[3]; iy++) + for (ijk[1] = idxBounds[2]; ijk[1] <= idxBounds[3]; ijk[1]++) { - p[1] = start[1] + iy * spacing[1]; - for (vtkIdType ix = idxBounds[0]; ix <= idxBounds[1]; ix++) + for (ijk[0] = idxBounds[0]; ijk[0] <= idxBounds[1]; ijk[0]++) { // skip processed points - const vtkIdType ptId = ix + dim[0] * (iy + dim[1] * iz); + const vtkIdType ptId = input->ComputePointId(ijk); if (maskArray[ptId] == 1) { continue; } - // For each grid point within the cell bound, interpolate values - p[0] = start[0] + ix * spacing[0]; + + // record point coordinates + double p[3]; + input->GetPoint(ptId, p); double pcoords[3]; int subId; @@ -876,14 +883,11 @@ class vtkProbeFilter::ProbeImageDataWorklet { public: ProbeImageDataWorklet(vtkProbeFilter* probeFilter, vtkDataSet* source, int srcBlockId, - const double start[3], const double spacing[3], const int dim[3], vtkPointData* outPD, - char* maskArray, int maxCellSize) + vtkImageData* input, vtkPointData* outPD, char* maskArray, int maxCellSize) : ProbeFilter(probeFilter) , Source(source) + , Input(input) , SrcBlockId(srcBlockId) - , Start(start) - , Spacing(spacing) - , Dim(dim) , OutPointData(outPD) , MaskArray(maskArray) , MaxCellSize(maxCellSize) @@ -924,7 +928,7 @@ public: } this->ProbeFilter->ProbeImagePointsInCell(cell, cellId, this->Source, this->SrcBlockId, - this->Start, this->Spacing, this->Dim, this->OutPointData, this->MaskArray, weights); + this->Input, this->OutPointData, this->MaskArray, weights); } } @@ -933,10 +937,8 @@ public: private: vtkProbeFilter* ProbeFilter; vtkDataSet* Source; + vtkImageData* Input; int SrcBlockId; - const double* Start; - const double* Spacing; - const int* Dim; vtkPointData* OutPointData; char* MaskArray; int MaxCellSize; @@ -952,25 +954,11 @@ void vtkProbeFilter::ProbePointsImageData( vtkPointData* outPD = output->GetPointData(); char* maskArray = this->MaskPoints->GetPointer(0); - //---------------------------------------- - double spacing[3]; - input->GetSpacing(spacing); - int extent[6]; - input->GetExtent(extent); - int dim[3]; - input->GetDimensions(dim); - double start[3]; - input->GetOrigin(start); - start[0] += static_cast<double>(extent[0]) * spacing[0]; - start[1] += static_cast<double>(extent[2]) * spacing[1]; - start[2] += static_cast<double>(extent[4]) * spacing[2]; - vtkIdType numSrcCells = source->GetNumberOfCells(); - if (numSrcCells > 0) { ProbeImageDataWorklet worklet( - this, source, srcIdx, start, spacing, dim, outPD, maskArray, source->GetMaxCellSize()); + this, source, srcIdx, input, outPD, maskArray, source->GetMaxCellSize()); vtkSMPTools::For(0, numSrcCells, worklet); } diff --git a/Filters/Core/vtkProbeFilter.h b/Filters/Core/vtkProbeFilter.h index 14ea5550889..ba11ab73ee8 100644 --- a/Filters/Core/vtkProbeFilter.h +++ b/Filters/Core/vtkProbeFilter.h @@ -300,8 +300,7 @@ private: void ProbePointsImageData( vtkImageData* input, int srcIdx, vtkDataSet* source, vtkImageData* output); void ProbeImagePointsInCell(vtkGenericCell* cell, vtkIdType cellId, vtkDataSet* source, - int srcBlockId, const double start[3], const double spacing[3], const int dim[3], - vtkPointData* outPD, char* maskArray, double* wtsBuff); + int srcBlockId, vtkImageData* input, vtkPointData* outPD, char* maskArray, double* wtsBuff); class ProbeImageDataWorklet; -- GitLab