in octree/tools/octree_prune.cpp [25:130]
void prune_octree(Octree& octree_out, const Octree& octree_in) {
const int bnd0[7][3] = { { 1, 1, 1 },
{ 2, 2, 2 }, { 4, 4, 4 }, { 8, 6, 8 },
{ 16, 10, 16 }, { 30, 18, 30 }, { 60, 36, 60 }
};
const int bnd1[7][3] = { { 1, 1, 1 },
{ 2, 2, 2 }, { 4, 3, 4 }, { 8, 5, 8 },
{ 15, 9, 15 }, { 30, 18, 30 }, { 60, 36, 60 }
};
// 0, 1, 2, 3, 4, 5, 6
vector<int> nnum_prune = { 1, 8, 64, 384, 2560, 16200, 129600 };
vector<int> nnum_nempty_prune = { 1, 8, 48, 320, 2025, 16200, 129600 };
// for the full layer
int depth = octree_in.info().depth();
int depth_full = octree_in.info().full_layer();
// CHECK(depth_full > 1);
// calculate the node number for the octree_out
vector<int> nnum(depth + 1, 0), nnum_nempty(depth + 1, 0);
for (int d = 0; d <= depth; ++d) {
nnum[d] = d > depth_full ? octree_in.info().node_num(d) : nnum_prune[d];
nnum_nempty[d] = d >= depth_full ? octree_in.info().node_num_nempty(d) : nnum_nempty_prune[d];
}
// init
OctreeInfo info_out = octree_in.info();
info_out.set_nnum(nnum.data());
info_out.set_nempty(nnum_nempty.data());
info_out.set_nnum_cum();
info_out.set_ptr_dis();
info_out.set_full_layer(2); // !!! full layer
octree_out.resize_octree(info_out.sizeof_octree());
octree_out.mutable_info() = info_out;
int channel_feature = octree_in.info().channel(OctreeInfo::kFeature);
int location_feature = octree_in.info().locations(OctreeInfo::kFeature);
int channel_label = octree_in.info().channel(OctreeInfo::kLabel);
int location_label = octree_in.info().locations(OctreeInfo::kLabel);
int channel_split = octree_in.info().channel(OctreeInfo::kSplit);
int location_split = octree_in.info().locations(OctreeInfo::kSplit);
for (int d = 1; d <= depth_full; ++d) {
int id = 0, j = 0;
int* child_out = octree_out.mutable_children_cpu(d);
const int* child_in = octree_in.children_cpu(d);
uintk* key_out = octree_out.mutable_key_cpu(d);
float* split_out = octree_out.mutable_split_cpu(d);
for (int i = 0; i < octree_in.info().node_num(d); ++i) {
uintk key = i, pt[3];
octree_in.key2xyz(pt, key, d);
if (pt[0] < bnd0[d][0] && pt[1] < bnd0[d][1] &&
pt[2] < bnd0[d][2]) {
if (pt[0] < bnd1[d][0] && pt[1] < bnd1[d][1] &&
pt[2] < bnd1[d][2]) {
child_out[j] = child_in[i] < 0 ? -1 : id++;
} else {
child_out[j] = -1; // empty
}
key_out[j] = key;
if ((location_split == -1 || d == depth) && channel_split != 0) {
split_out[j] = child_out[j] < 0 ? 0.0f : 1.0f;
}
// update j
j++;
}
}
}
// copy directly
for (int d = depth; d > depth_full; --d) {
int num = octree_in.info().node_num(d);
const int* child_in = octree_in.children_cpu(d);
int* child_out = octree_out.mutable_children_cpu(d);
std::copy_n(child_in, num, child_out);
const uintk* key_in = octree_in.key_cpu(d);
uintk* key_out = octree_out.mutable_key_cpu(d);
std::copy_n(key_in, num, key_out);
if (location_feature == -1 || d == depth) {
const float * feature_in = octree_in.feature_cpu(d);
float* feature_out = octree_out.mutable_feature_cpu(d);
std::copy_n(feature_in, num * channel_feature, feature_out);
}
if ((location_label == -1 || d == depth) && channel_label != 0) {
const float * label_in = octree_in.label_cpu(d);
float* label_out = octree_out.mutable_label_cpu(d);
std::copy_n(label_in, num, label_out);
}
if ((location_split == -1 || d == depth) && channel_split != 0) {
const float * split_in = octree_in.split_cpu(d);
float* split_out = octree_out.mutable_split_cpu(d);
std::copy_n(split_in, num, split_out);
}
}
}