// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause // Test the vtkImageStencilIterator under various conditions #include "vtkImageData.h" #include "vtkImageStencilData.h" #include "vtkImageStencilIterator.h" #include "vtkNew.h" #include "vtkTesting.h" #include //------------------------------------------------------------------------------ // Provides a pseudo-random value at each position static unsigned char VoxelValue(int i, int j, int k) { static bool seeded = false; static unsigned int randseq[127]; if (!seeded) { unsigned int seed = 230981U; for (unsigned int c = 0; c < 127; c++) { randseq[c] = 1664525U * seed + 1013904223U; seed = randseq[c]; } seeded = true; } unsigned int l = (k * 127 * 127 + j * 127 + i) % (4 * 127); unsigned int m = l / 4; unsigned int n = l % 4; return static_cast(randseq[m] >> (8 * n)); } //------------------------------------------------------------------------------ // Generate a test image static void GenerateImage(vtkImageData* image, int extent[6]) { image->Initialize(); image->SetExtent(extent); image->AllocateScalars(VTK_UNSIGNED_CHAR, 1); unsigned char* ptr = static_cast(image->GetScalarPointer()); for (int k = extent[4]; k <= extent[5]; k++) { for (int j = extent[2]; j <= extent[3]; j++) { for (int i = extent[0]; i <= extent[1]; i++) { *ptr++ = VoxelValue(i, j, k); } } } } //------------------------------------------------------------------------------ // Generate a test stencil static void GenerateStencil(vtkImageStencilData* stencil, int extent[6]) { stencil->Initialize(); stencil->SetExtent(extent); stencil->AllocateExtents(); for (int k = extent[4]; k <= extent[5]; k++) { for (int j = extent[2]; j <= extent[3]; j++) { for (int i = extent[0]; i <= extent[1]; i++) { if (VoxelValue(i, j, k) > 127) { // adjacent extents will be joined stencil->InsertNextExtent(i, i, j, k); } } } } } //------------------------------------------------------------------------------ // check that stencil and image match over the given extents static bool CheckStencilExtents(int imageExt[6], int stencilExt[6], int extent[6]) { vtkNew image; GenerateImage(image, imageExt); vtkNew stencil; GenerateStencil(stencil, stencilExt); vtkImageStencilIterator iter; iter.Initialize(image, stencil, extent); bool match = true; int i = extent[0]; int j = extent[2]; int k = extent[4]; for (; !iter.IsAtEnd(); iter.NextSpan()) { bool inside = iter.IsInStencil(); for (unsigned char* p = iter.BeginSpan(); p != iter.EndSpan(); p++) { match &= (*p == VoxelValue(i, j, k)); if (i >= stencilExt[0] && i <= stencilExt[1] && j >= stencilExt[2] && j <= stencilExt[3] && k >= stencilExt[4] && k <= stencilExt[5]) { match &= (!inside) ^ (*p > 127); } else { match &= !inside; } i++; } if (i == extent[1] + 1) { i = extent[0]; j++; if (j == extent[3] + 1) { j = extent[2]; k++; } } } return match; } //------------------------------------------------------------------------------ int TestImageStencilIterator(int argc, char* argv[]) { vtkNew testing; for (int cc = 1; cc < argc; cc++) { testing->AddArgument(argv[cc]); } int extents[57][6] = { // all extents the same, all start at 0,0,0 { 0, 9, 0, 9, 0, 9 }, { 0, 9, 0, 9, 0, 9 }, { 0, 9, 0, 9, 0, 9 }, // smaller stencil extent in X direction { 0, 9, 0, 9, 0, 9 }, { 2, 4, 0, 9, 0, 9 }, { 0, 9, 0, 9, 0, 9 }, // smaller stencil extent in Y direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 0, 9 }, { 0, 9, 0, 9, 0, 9 }, // smaller stencil extent in Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 0, 9, 5, 7 }, { 0, 9, 0, 9, 0, 9 }, // smaller stencil extent in Y and Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 5, 7 }, { 0, 9, 0, 9, 0, 9 }, // shrink the execute extent // smaller stencil extent in X direction { 0, 9, 0, 9, 0, 9 }, { 2, 4, 0, 9, 0, 9 }, { 2, 4, 0, 9, 0, 9 }, // smaller stencil extent in Y direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 0, 9 }, { 0, 9, 3, 8, 0, 9 }, // smaller stencil extent in Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 0, 9, 5, 7 }, { 0, 9, 0, 9, 5, 7 }, // smaller stencil extent in Y and Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 5, 7 }, { 0, 9, 3, 8, 5, 7 }, // shrink the execute extent more // smaller stencil extent in X direction { 0, 9, 0, 9, 0, 9 }, { 2, 4, 0, 9, 0, 9 }, { 2, 4, 3, 8, 0, 9 }, // smaller stencil extent in Y direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 0, 9 }, { 0, 9, 3, 8, 3, 8 }, // smaller stencil extent in Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 0, 9, 5, 7 }, { 0, 9, 3, 8, 5, 7 }, // smaller stencil extent in Y and Z direction { 0, 9, 0, 9, 0, 9 }, { 0, 9, 3, 8, 5, 7 }, { 0, 9, 4, 9, 6, 9 }, // stencil and execute extent do not overlap { 0, 10, 3, 8, 2, 19 }, { 0, 10, 3, 8, 2, 7 }, { 0, 10, 3, 8, 8, 19 }, { 0, 10, 3, 8, 2, 19 }, { 0, 10, 3, 8, 8, 19 }, { 0, 10, 3, 8, 2, 7 }, { 0, 10, 3, 8, 2, 19 }, { 0, 10, 0, 4, 2, 19 }, { 0, 10, 6, 8, 2, 19 }, { 0, 10, 3, 8, 2, 19 }, { 0, 10, 6, 8, 2, 19 }, { 0, 10, 3, 4, 2, 19 }, { 0, 10, 3, 8, 2, 19 }, { 6, 10, 3, 8, 2, 19 }, { 0, 3, 3, 8, 2, 19 }, { 0, 10, 3, 8, 2, 19 }, { 0, 5, 3, 8, 2, 19 }, { 6, 10, 3, 8, 2, 19 }, }; int rval = EXIT_SUCCESS; for (int i = 0; i < 57; i += 3) { if (!CheckStencilExtents(extents[i], extents[i + 1], extents[i + 2])) { std::cerr << "Failed with these extents:\n"; std::cerr << "Image: " << extents[i][0] << " " << extents[i][1] << " " << extents[i][2] << " " << extents[i][3] << " " << extents[i][4] << " " << extents[i][5] << "\n"; std::cerr << "Stencil: " << extents[i + 1][0] << " " << extents[i + 1][1] << " " << extents[i + 1][2] << " " << extents[i + 1][3] << " " << extents[i + 1][4] << " " << extents[i + 1][5] << "\n"; std::cerr << "Execute: " << extents[i + 2][0] << " " << extents[i + 2][1] << " " << extents[i + 2][2] << " " << extents[i + 2][3] << " " << extents[i + 2][4] << " " << extents[i + 2][5] << "\n"; rval = EXIT_FAILURE; } } return rval; }