void generateManhattanDistanceSDF()

in src/esp/geo/VoxelUtils.cpp [90:185]


void generateManhattanDistanceSDF(
    std::shared_ptr<esp::geo::VoxelWrapper>& voxelWrapper,
    const std::string& gridName) {
  // check to see if Interior/Exterior grid exists, if not, generate it
  auto v_grid = voxelWrapper->getVoxelGrid();
  auto m_voxelGridDimensions = v_grid->getVoxelGridDimensions();

  if (!v_grid->gridExists("InteriorExterior")) {
    generateInteriorExteriorVoxelGrid(voxelWrapper);
  }

  // create new intGrid and copy data from interior/exterior grid
  v_grid->addGrid<int>(gridName);
  auto intExtGrid = v_grid->getGrid<int>("InteriorExterior");
  auto sdfGrid = v_grid->getGrid<int>(gridName);

  Cr::Utility::copy(intExtGrid, sdfGrid);

  // 1st sweep
  for (int i = 0; i < m_voxelGridDimensions[0]; i++) {
    for (int j = 0; j < m_voxelGridDimensions[1]; j++) {
      for (int k = 0; k < m_voxelGridDimensions[2]; k++) {
        int i_behind = INT_MAX, j_behind = INT_MAX, k_behind = INT_MAX;
        if (v_grid->isValidIndex(Mn::Vector3i(i - 1, j, k))) {
          i_behind = abs(std::max(sdfGrid[i - 1][j][k], -INT_MAX));
        }
        if (v_grid->isValidIndex(Mn::Vector3i(i, j - 1, k))) {
          j_behind = abs(std::max(sdfGrid[i][j - 1][k], -INT_MAX));
        }
        if (v_grid->isValidIndex(Mn::Vector3i(i, j, k - 1))) {
          k_behind = abs(std::max(sdfGrid[i][j][k - 1], -INT_MAX));
        }
        int curVal = sdfGrid[i][j][k];
        int closest = 0;
        if (i_behind <= j_behind && i_behind <= k_behind) {
          // i_behind is closest to nearest obstacle.
          closest = i_behind;
        } else if (j_behind <= i_behind && j_behind <= k_behind) {
          // j_behind is closest to nearest obstacle.
          closest = j_behind;
        } else {
          // k_behind is closest or tied for closest to nearest obstacle.
          closest = k_behind;
        }
        // Get the minimum of the cell that's closest to an obstacle and the
        // current distance to an obstacle, and multiply by the true sign of
        // curVal
        if (closest == INT_MAX)
          closest--;
        curVal = (static_cast<int>(curVal > 0) - static_cast<int>(curVal < 0)) *
                 std::min(abs(std::max(curVal, -INT_MAX)), closest + 1);
        sdfGrid[i][j][k] = curVal;
      }
    }
  }
  // second sweep
  for (int i = m_voxelGridDimensions[0] - 1; i >= 0; i--) {
    for (int j = m_voxelGridDimensions[1] - 1; j >= 0; j--) {
      for (int k = m_voxelGridDimensions[2] - 1; k >= 0; k--) {
        int curVal = sdfGrid[i][j][k];
        if (curVal == 0)
          continue;
        int i_ahead = INT_MAX, j_ahead = INT_MAX, k_ahead = INT_MAX;
        if (v_grid->isValidIndex(Mn::Vector3i(i + 1, j, k))) {
          i_ahead = abs(std::max(sdfGrid[i + 1][j][k], -INT_MAX));
        }
        if (v_grid->isValidIndex(Mn::Vector3i(i, j + 1, k))) {
          j_ahead = abs(std::max(sdfGrid[i][j + 1][k], -INT_MAX));
        }
        if (v_grid->isValidIndex(Mn::Vector3i(i, j, k + 1))) {
          k_ahead = abs(std::max(sdfGrid[i][j][k + 1], -INT_MAX));
        }

        int closest = INT_MAX - 1;
        if (i_ahead <= j_ahead && i_ahead <= k_ahead) {
          // i_ahead is closest to nearest obstacle.
          closest = i_ahead;
        } else if (j_ahead <= i_ahead && j_ahead <= k_ahead) {
          // j_ahead is closest to nearest obstacle.
          closest = j_ahead;
        } else {
          // k_ahead is closest or tied for closest to nearest obstacle.
          closest = k_ahead;
        }
        // Get the minimum of the cell that's closest to an obstacle and the
        // current distance to an obstacle, and multiply by the true sign of
        // curVal
        if (closest == INT_MAX)
          closest--;
        curVal = (static_cast<int>(curVal > 0) - static_cast<int>(curVal < 0)) *
                 std::min(abs(std::max(curVal, -INT_MAX)), closest + 1);
        sdfGrid[i][j][k] = curVal;
      }
    }
  }
}