-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOctreeBase.cpp
More file actions
266 lines (232 loc) · 7.8 KB
/
OctreeBase.cpp
File metadata and controls
266 lines (232 loc) · 7.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#include "ChunkedAllocator.h"
#include "OctreeNode.h"
#include "Point.h"
#include "code.h"
#include <algorithm>
#include <cmath>
#include <iostream>
#include <stdint.h>
#include <stdio.h>
#include <vector>
namespace Octomap {
const int MAX_POINTS_PER_NODE = 4;
const int MAX_DEPTH = 16;
const int MAX_OBJECTS_PER_NODE = 4;
struct Block {
std::array<std::array<double, 2>, 2> pixels;
};
template <typename DATA_TYPE, typename INNER_NODE = OctreeInnerNode<DATA_TYPE>,
typename LEAF_NODE = OctreeLeafNode<DATA_TYPE>>
class Octree {
protected:
using Path = std::array<LEAF_NODE *, 8>;
public:
Octree(/*int map_scale[2], double voxel_scale, int min_occup_threshold, double
min_ray_length, double max_ray_length, int max_submap_num, int K,
double min_x, double min_y, double min_z, double max_x, double max_y,
double max_z*/
) { /*
this->max_size_xy = map_scale[0];
this->max_size_z = map_scale[1];
this->voxel_scale = voxel_scale;
this->min_occup_threshold = min_occup_threshold;
this->min_ray_length = min_ray_length;
this->max_ray_length = max_ray_length;
this->max_submap_num = max_submap_num;
this->K = K;
*/
// nodes.push_back(OctreeNode(0, false));
this->allocator = new ChunkedAllocator<Point>();
this->initialize_field();
this->construct_octree();
this->initialize_submap_fields();
}
void initialize_field() {}
void construct_octree() {}
void initialize_submap_fields() {}
bool is_occupy() {}
void recast_pcl_to_map() {}
void recast_depth_to_map() {}
void fuse_submaps() {}
std::vector<double> get_occup_voxels() {}
// return corresponding node and depth given the morton code
std::pair<LEAF_NODE const *, int> getNode(const Code &code) const {
LEAF_NODE const *node = &getRoot();
// depth 0 = leaf node
for (int depth = depth_ - 1; depth > code.getDepth(); --depth) {
INNER_NODE const &inner_node = static_cast<INNER_NODE const &>(*node);
// if reach leaf node, return
if (inner_node.is_leaf) {
return std::make_pair(node, depth + 1);
}
// otherwise, move to next level
node = &getChild(inner_node, depth, code.getChildIndex(depth));
}
return std::make_pair(node, code.getDepth());
}
std::pair<Path, int> getNodePath(const Code &code) {
Path path;
path[depth_] = static_cast<LEAF_NODE *>(&getRoot());
int depth = depth_;
for (; depth > code.getDepth(); --depth) {
INNER_NODE &node = static_cast<INNER_NODE &>(*path[depth]);
// if node is leaf node, no need to traverse down
if (node.is_leaf) {
break;
}
int child_depth = depth - 1;
path[child_depth] = static_cast<LEAF_NODE *>(
&getChild(node, child_depth, code.getChildIndex(child_depth)));
}
return std::make_pair(path, depth);
}
Path insertNode(const Code &code) {
Path path;
path[depth_] = static_cast<LEAF_NODE *>(&getRoot());
insertNode(code, path, depth_);
return path;
}
void insertNode(const Code &code, Path &path, int depth) {
// depth 0 = leaf node
// TODO: debugging the depth
// std::cout <<"code depth:"<< code.getDepth() << std::endl;
for (; depth > code.getDepth(); --depth) {
INNER_NODE &node = static_cast<INNER_NODE &>(*(path[depth]));
// std::cout <<"is leaf: "<< node.is_leaf<<std::endl;
if (!hasChildren(node)) {
createChildren(node, depth);
}
int child_depth = depth - 1;
path[child_depth] = static_cast<LEAF_NODE *>(
&getChild(node, child_depth, code.getChildIndex(child_depth)));
}
}
DATA_TYPE const *search(Code const &code) const {
auto [node, depth] = getNode(code);
if (depth == code.getDepth()) {
// std::cout <<"same depth"<<std::endl;
return &(node->value);
} else {
return nullptr;
}
}
static LEAF_NODE &getChild(INNER_NODE const &inner_node, int child_depth,
int child_idx) {
if (child_depth == 0) {
return getLeafChild(inner_node, child_idx);
} else {
return getInnerChild(inner_node, child_idx);
}
}
static LEAF_NODE &getLeafChild(INNER_NODE const &inner_node, int child_idx) {
return getLeafChildren(inner_node)[child_idx];
}
static INNER_NODE &getInnerChild(INNER_NODE const &inner_node,
int child_idx) {
return getInnerChildren(inner_node)[child_idx];
}
static std::array<LEAF_NODE, 8> &
getLeafChildren(INNER_NODE const &inner_node) {
return *static_cast<std::array<LEAF_NODE, 8> *>(inner_node.children);
}
static std::array<INNER_NODE, 8> &
getInnerChildren(INNER_NODE const &inner_node) {
return *static_cast<std::array<INNER_NODE, 8> *>(inner_node.children);
}
bool createChildren(INNER_NODE &node, int depth) {
// Cannot rcreate children for non-leaf node
if (!node.is_leaf) {
return false;
}
// if pointer to children nodes is null, create children
if (!node.children) {
// second lowest level, create leaf node children
if (1 == depth) {
node.children = new std::array<LEAF_NODE, 8>();
num_leaf_nodes += 8;
num_inner_leaf_node -= 1;
} else {
node.children = new std::array<INNER_NODE, 8>();
num_inner_leaf_node += 7;
}
num_inner_node += 1;
}
if (1 == depth) {
for (LEAF_NODE &child : getLeafChildren(node)) {
child = static_cast<LEAF_NODE &>(node);
}
} else {
for (INNER_NODE &child : getInnerChildren(node)) {
decltype(child.children) children = child.children;
child = node;
child.children = children;
}
}
node.is_leaf = false;
return true;
}
static bool hasChildren(INNER_NODE const &node) noexcept {
return !isLeaf(node);
}
static bool hasChildren(LEAF_NODE const *node, int depth) noexcept {
return 0 != depth && hasChildren(static_cast<INNER_NODE const &>(*node));
}
static bool isLeaf(INNER_NODE const &node) noexcept { return node.is_leaf; }
static bool isLeaf(LEAF_NODE const *node, int depth) noexcept {
return 0 == depth || isLeaf(static_cast<INNER_NODE const &>(*node));
}
INNER_NODE const &getRoot() const { return root_; }
INNER_NODE &getRoot() { return root_; }
const int &getNumLeafNodes() const { return num_leaf_nodes; }
const int &getNumInnerNodes() const { return num_inner_node; }
const int &getNumInnerLeafNodes() const { return num_inner_leaf_node; }
private:
// Number of levels for the octree. Has to be [2, 21].
// This determines the maximum volume that can be represented by the map
// resolution * 2^(depth_levels) meter in each dimension.
int depth_ = 16;
Point minBound;
Point maxBound;
ChunkedAllocator<Point> *allocator;
Path path; // represent arrays of nodes for each level
INNER_NODE root_;
int num_leaf_nodes = 0;
int num_inner_leaf_node = 0;
int num_inner_node = 0;
/*
std::vector<int> queryPoint(int node_idx, uint32_t code, int depth)
{
const OctreeNode &node = nodes[node_idx];
if (depth == MAX_DEPTH)
{
std::vector<int> result;
for (int i = 0; i < node.data_index; ++i)
{
result.push_back(data_points[node.data_index + i].first);
}
return result;
}
else
{
int child_idx = get_child_index(code, depth);
if (node.children[child_idx] != -1)
{
return queryPoint(node.children[child_idx], code, depth + 1);
// if not set, return empty result
}
else
{
return {};
}
}
}
*/
/*
void sorted_morton_code()
{
std::sort(nodes.begin(), nodes.end(), [](const OctreeNode &a, const
OctreeNode &b) { return a.code < b.code; });
}
*/
};
} // namespace Octomap