void MergeOctrees::merge_octree()

in octree/octree/merge_octrees.cpp [114:198]


void MergeOctrees::merge_octree() {
  typedef typename KeyTrait<uintk>::uints uints;

  // omp_set_num_threads(8);
  //#pragma omp parallel for
  for (int i = 0; i < batch_size_; ++i) {
    // copy key
    // the channel and location of key is 1 and -1 
    for (int d = 0; d < depth_ + 1; ++d) {
      if (!info_batch_.has_property(OctreeInfo::kKey)) break;
      int p = i * (depth_ + 1) + d;
      uintk* des = octbatch_parser_.mutable_key_cpu(d) + nnum_cum_layer_[p];
      const uintk* src = octree_parsers_[i].key_cpu(d);
      for (int j = 0; j < nnum_[p]; ++j) {
        des[j] = src[j];
        uints* ptr = reinterpret_cast<uints*>(des + j);
        ptr[3] = i;
      }
    }

    // copy children
    // by default, the channel and location of children is 1 and -1,
    for (int d = 0; d < depth_ + 1; ++d) {
      if (!info_batch_.has_property(OctreeInfo::kChild)) break;
      int p = i * (depth_ + 1) + d;
      int* des = octbatch_parser_.mutable_children_cpu(d) + nnum_cum_layer_[p];
      const int* src = octree_parsers_[i].children_cpu(d);
      for (int j = 0; j < nnum_[p]; ++j) {
        des[j] = -1 == src[j] ? src[j] : src[j] + nnum_cum_nempty_layer_[p];
      }
    }

    // copy data: !NOTE! the type of signal is float!!!
    int feature_channel = info_batch_.channel(OctreeInfo::kFeature);
    int feature_location = info_batch_.locations(OctreeInfo::kFeature);
    int depth_start = feature_location == depth_ ? depth_ : 0;
    for (int d = depth_start; d < depth_ + 1; ++d) {
      if (!info_batch_.has_property(OctreeInfo::kFeature)) break;
      int p = i * (depth_ + 1) + d;
      for (int c = 0; c < feature_channel; c++) {
        float* des = octbatch_parser_.mutable_feature_cpu(d) +
                     c * nnum_batch_[d] + nnum_cum_layer_[p];
        const float* src = octree_parsers_[i].feature_cpu(d) + c * nnum_[p];
        for (int j = 0; j < nnum_[p]; ++j) { des[j] = src[j]; }
      }
    }

    // copy label: !NOTE! the type of label is float!!!
    int label_location = info_batch_.locations(OctreeInfo::kLabel);
    depth_start = label_location == depth_ ? depth_ : 0;
    for (int d = depth_start; d < depth_ + 1; ++d) {
      if (!info_batch_.has_property(OctreeInfo::kLabel)) break;
      int p = i * (depth_ + 1) + d;
      float* des = octbatch_parser_.mutable_label_cpu(d) + nnum_cum_layer_[p];
      const float* src = octree_parsers_[i].label_cpu(d);
      for (int j = 0; j < nnum_[p]; ++j) { des[j] = src[j]; }
    }

    // copy split label: !NOTE! the type of label is float!!!
    int split_location = info_batch_.locations(OctreeInfo::kSplit);
    depth_start = split_location == depth_ ? depth_ : 0;
    for (int d = depth_start; d < depth_ + 1; ++d) {
      if (!info_batch_.has_property(OctreeInfo::kSplit)) break;
      int p = i * (depth_ + 1) + d;
      float* des = octbatch_parser_.mutable_split_cpu(d) + nnum_cum_layer_[p];
      const float* src = octree_parsers_[i].split_cpu(d);
      for (int j = 0; j < nnum_[p]; ++j) des[j] = src[j];
    }
  }

  // calc and set neighbor info
  for (int d = 1; d < depth_ + 1; ++d) {
    if (!info_batch_.has_property(OctreeInfo::kNeigh)) break;
    CHECK(info_batch_.has_property(OctreeInfo::kChild));

    if (d <= full_layer_) {
      calc_neigh_cpu(octbatch_parser_.mutable_neighbor_cpu(d), d, batch_size_);
    } else {
      calc_neigh_cpu(octbatch_parser_.mutable_neighbor_cpu(d),
                     octbatch_parser_.neighbor_cpu(d - 1),
                     octbatch_parser_.children_cpu(d - 1),
                     octbatch_parser_.info().node_num(d - 1));
    }
  }
}