void NeighHelper::init_neigh_index()

in octree/octree/octree_nn.cpp [6:108]


void NeighHelper::init_neigh_index() {
  const vector<std::pair<string, int> > kernel_type{
    { "333", 0 }, { "111", 1 }, { "222", 2 },
    { "311", 3 }, { "131", 4 }, { "113", 5 },
    { "331", 6 }, { "313", 7 }, { "133", 8 } };

  const vector<vector<int> > vec{ {} /* 333, 27 */, { 13 } /* 111, 1 */,
    { 13, 14, 16, 17, 22, 23, 25, 26 } /* 222, 8, 8 octants */,
    {  4, 13, 22 } /* 311, 3 */,
    { 10, 13, 16 } /* 131, 3 */,
    { 12, 13, 14 } /* 113, 3 */,
    { 1,  4,  7, 10, 13, 16, 19, 22, 25 } /* 331, 9 */,
    { 3,  4,  5, 12, 13, 14, 21, 22, 23 } /* 313, 9 */,
    { 9, 10, 11, 12, 13, 14, 15, 16, 17 } /* 133, 9 */ };

  // init
  ni_map_.insert(kernel_type.begin(), kernel_type.end());
  ni_.resize(kernel_type.size());

  // ni for kernel_size=333
  ni_[0].assign(216, 0);
  int* ni3 = ni_[0].data();
  int id = 0;
  for (int ijk = 0; ijk < 8; ++ijk) {
    for (int xyz = 0; xyz < 27; ++xyz) {
      int k = ijk % 2, p = ijk / 2;
      int j = p % 2, i = p / 2;

      int z = xyz % 3, q = xyz / 3;
      int y = q % 3, x = q / 3;

      ni3[id++] = ((x + i) << 4) | ((y + j) << 2) | (z + k);
    }
  }

  // ni for other kernel_sizes
  for (int k = 1; k < kernel_type.size(); ++k) {
    int sz = vec[k].size();
    ni_[k].assign(8 * sz, 0);
    int* ni = ni_[k].data();
    for (int i = 0; i < 8; ++i) {
      for (int j = 0; j < sz; ++j) {
        ni[i * sz + j] = ni3[i * 27 + vec[k][j]];
      }
    }
  }

  // init the array parent & displacement
  id = 0;
  int tmp[64];
  displacement_.assign(64, 0);
  int* dis_ptr = displacement_.data();
  for (int x = 1; x < 5; ++x) {
    for (int y = 1; y < 5; ++y) {
      for (int z = 1; z < 5; ++z) {
        int x1 = x / 2;
        int xb = x % 2;
        int y1 = y / 2;
        int yb = y % 2;
        int z1 = z / 2;
        int zb = z % 2;

        tmp[id] = x1 * 9 + y1 * 3 + z1;
        dis_ptr[id] = (xb << 2) | (yb << 1) | zb;
        id++;
      }
    }
  }

  parent_.assign(512, 0);
  int* parent_ptr = parent_.data();
  for (int i = 0; i < 8; ++i) {
    for (int j = 0; j < 64; ++j) {
      parent_ptr[i * 64 + j] = ni3[i * 27 + tmp[j]];
    }
  }

  // init the bilinear table
  bilinear_.assign(512, -1);
  const int mask[8][3] = {                       // bilinear weights:
    {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {1, 0, 0},  // 27, 9, 9, 9
    {0, 1, 1}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},  //  3, 3, 3, 1
  };
  for (int i = 0; i < 8; ++i) {
    // i -> xyz
    int z0 = i % 2, t = i / 2;
    int y0 = t % 2, x0 = t / 2;

    for (int j = 0; j < 8; ++j) {
      // j -> xyz
      int z1 = j % 2, s = j / 2;
      int y1 = s % 2, x1 = s / 2;

      for (int k = 0; k < 8; ++k) {
        int x2 = x0 + 1 + mask[k][0] * (2 * x1 - 1);
        int y2 = y0 + 1 + mask[k][1] * (2 * y1 - 1);
        int z2 = z0 + 1 + mask[k][2] * (2 * z1 - 1);

        bilinear_[(i << 6) | (j << 3) | k] = (x2 << 4) | (y2 << 2) | z2;
      }
    }
  }
}