10 #include <unordered_map>
25 static const std::unordered_map<std::string, std::string>
27 {
"origin",
"Origin coordinates."},
28 {
"size",
"Size of the Octree."},
29 {
"color",
"Color of the point."},
30 {
"point",
"Coordinates of the point."},
31 {
"max_depth",
"Maximum depth of the octree."},
32 {
"point_cloud",
"Input point cloud."},
34 "A small expansion size such that the octree is slightly "
35 "bigger than the original point cloud bounds to accomodate "
41 py::class_<OctreeNodeInfo, std::shared_ptr<OctreeNodeInfo>>
42 octree_node_info(m,
"OctreeNodeInfo",
43 "OctreeNode's information. OctreeNodeInfo is "
44 "computed on the fly, "
45 "not stored with the Node.");
46 octree_node_info.def(py::init([](
const Eigen::Vector3d &origin,
double size,
47 size_t depth,
size_t child_index) {
51 "origin"_a,
"size"_a,
"depth"_a,
"child_index"_a);
55 std::ostringstream repr;
56 repr <<
"OctreeNodeInfo with origin ["
60 repr <<
", size " << node_info.
size_;
61 repr <<
", depth " << node_info.
depth_;
67 "(3, 1) float numpy array: Origin coordinate of the node.")
69 "float: Size of the node.")
71 "int: Depth of the node to the root. The root is of "
75 "int: Node's child index of itself. For non-root nodes, "
76 "child_index is 0~7; root node's child_index is -1.");
80 py::class_<OctreeNode, PyOctreeNode<OctreeNode>,
81 std::shared_ptr<OctreeNode>>
82 octree_node(m,
"OctreeNode",
"The base class for octree node.");
83 octree_node.def(
"__repr__", [](
const OctreeNode &octree_node) {
84 return "OctreeNode instance.";
89 py::class_<OctreeInternalNode, PyOctreeNode<OctreeInternalNode>,
90 std::shared_ptr<OctreeInternalNode>,
OctreeNode>
91 octree_internal_node(m,
"OctreeInternalNode",
92 "OctreeInternalNode class, containing "
93 "OctreeNode children.");
96 [](
const OctreeInternalNode &internal_node) {
97 size_t num_children = 0;
98 for (
const std::shared_ptr<OctreeNode> &child :
99 internal_node.children_) {
100 if (child != nullptr) {
104 std::ostringstream repr;
105 repr <<
"OctreeInternalNode with " << num_children
106 <<
" non-empty child nodes";
110 "get_init_function", &OctreeInternalNode::GetInitFunction,
111 "Get lambda function for initializing OctreeInternalNode. "
112 "When the init function is called, an empty "
113 "OctreeInternalNode is created.")
114 .def_static(
"get_update_function",
115 &OctreeInternalNode::GetUpdateFunction,
116 "Get lambda function for updating OctreeInternalNode. "
117 "This update function does nothing.");
118 py::detail::bind_default_constructor<OctreeInternalNode>(
119 octree_internal_node);
120 py::detail::bind_copy_functions<OctreeInternalNode>(octree_internal_node);
121 octree_internal_node.def_readwrite(
"children",
122 &OctreeInternalNode::children_,
123 "List of children Nodes.");
127 py::class_<OctreeInternalPointNode, PyOctreeNode<OctreeInternalPointNode>,
128 std::shared_ptr<OctreeInternalPointNode>, OctreeInternalNode>
129 octree_internal_point_node(
130 m,
"OctreeInternalPointNode",
131 "OctreeInternalPointNode class is an "
132 "OctreeInternalNode with a list of point "
133 "indices (from point cloud) belonging to "
134 "children of this node.");
135 octree_internal_point_node
137 [](
const OctreeInternalPointNode &internal_point_node) {
138 size_t num_children = 0;
139 for (
const std::shared_ptr<OctreeNode> &child :
140 internal_point_node.children_) {
141 if (child != nullptr) {
145 std::ostringstream repr;
146 repr <<
"OctreeInternalPointNode with " << num_children
147 <<
" non-empty child nodes and "
148 << internal_point_node.indices_.size() <<
" points";
151 .def_readwrite(
"indices", &OctreeInternalPointNode::indices_,
152 "List of point cloud point indices "
153 "contained in children nodes.")
154 .def_static(
"get_init_function",
155 &OctreeInternalPointNode::GetInitFunction,
156 "Get lambda function for initializing "
157 "OctreeInternalPointNode. "
158 "When the init function is called, an empty "
159 "OctreeInternalPointNode is created.")
161 "get_update_function",
162 &OctreeInternalPointNode::GetUpdateFunction,
163 "Get lambda function for updating OctreeInternalPointNode. "
164 "When called, the update function adds the input "
165 "point index to the corresponding node's list of "
166 "indices of children points.");
167 py::detail::bind_default_constructor<OctreeInternalPointNode>(
168 octree_internal_point_node);
169 py::detail::bind_copy_functions<OctreeInternalPointNode>(
170 octree_internal_point_node);
171 octree_internal_point_node.def_readwrite(
172 "children", &OctreeInternalPointNode::children_,
173 "List of children Nodes.");
177 py::class_<OctreeLeafNode, PyOctreeLeafNode<OctreeLeafNode>,
178 std::shared_ptr<OctreeLeafNode>, OctreeNode>
179 octree_leaf_node(m,
"OctreeLeafNode",
"OctreeLeafNode base class.");
182 [](
const OctreeLeafNode &leaf_node) {
183 std::ostringstream repr;
184 repr <<
"OctreeLeafNode base class";
187 .def(
"__eq__", &OctreeLeafNode::operator==,
"other"_a,
188 "Check equality of OctreeLeafNode.")
189 .def(
"clone", &OctreeLeafNode::Clone,
"Clone this OctreeLeafNode.");
194 py::class_<OctreeColorLeafNode, PyOctreeLeafNode<OctreeColorLeafNode>,
195 std::shared_ptr<OctreeColorLeafNode>, OctreeLeafNode>
196 octree_color_leaf_node(m,
"OctreeColorLeafNode",
197 "OctreeColorLeafNode class is an "
198 "OctreeLeafNode containing color.");
199 octree_color_leaf_node
201 [](
const OctreeColorLeafNode &color_leaf_node) {
202 std::ostringstream repr;
203 repr <<
"OctreeColorLeafNode with color ["
204 << color_leaf_node.color_(0) <<
", "
205 << color_leaf_node.color_(1) <<
", "
206 << color_leaf_node.color_(2) <<
"]";
209 .def_readwrite(
"color", &OctreeColorLeafNode::color_,
210 "(3, 1) float numpy array: Color of the node.")
211 .def_static(
"get_init_function",
212 &OctreeColorLeafNode::GetInitFunction,
213 "Get lambda function for initializing OctreeLeafNode. "
214 "When the init function is called, an empty "
215 "OctreeColorLeafNode is created.")
216 .def_static(
"get_update_function",
217 &OctreeColorLeafNode::GetUpdateFunction,
"color"_a,
218 "Get lambda function for updating OctreeLeafNode. When "
219 "called, the update function updates the corresponding "
220 "node with the input color.");
222 py::detail::bind_default_constructor<OctreeColorLeafNode>(
223 octree_color_leaf_node);
224 py::detail::bind_copy_functions<OctreeColorLeafNode>(
225 octree_color_leaf_node);
228 py::class_<OctreePointColorLeafNode,
229 PyOctreeLeafNode<OctreePointColorLeafNode>,
230 std::shared_ptr<OctreePointColorLeafNode>, OctreeLeafNode>
231 octree_point_color_leaf_node(m,
"OctreePointColorLeafNode",
232 "OctreePointColorLeafNode class is an "
233 "OctreeLeafNode containing color.");
234 octree_point_color_leaf_node
236 [](
const OctreePointColorLeafNode &color_leaf_node) {
237 std::ostringstream repr;
238 repr <<
"OctreePointColorLeafNode with color ["
239 << color_leaf_node.color_(0) <<
", "
240 << color_leaf_node.color_(1) <<
", "
241 << color_leaf_node.color_(2) <<
"] "
242 <<
"containing " << color_leaf_node.indices_.size()
246 .def_readwrite(
"color", &OctreePointColorLeafNode::color_,
247 "(3, 1) float numpy array: Color of the node.")
248 .def_readwrite(
"indices", &OctreePointColorLeafNode::indices_,
249 "List of point cloud point indices "
250 "contained in this leaf node.")
251 .def_static(
"get_init_function",
252 &OctreePointColorLeafNode::GetInitFunction,
253 "Get lambda function for initializing OctreeLeafNode. "
254 "When the init function is called, an empty "
255 "OctreePointColorLeafNode is created.")
256 .def_static(
"get_update_function",
257 &OctreePointColorLeafNode::GetUpdateFunction,
"idx"_a,
259 "Get lambda function for updating OctreeLeafNode. When "
260 "called, the update function updates the corresponding "
261 "node with the new point index and the input color.");
263 py::detail::bind_default_constructor<OctreePointColorLeafNode>(
264 octree_point_color_leaf_node);
265 py::detail::bind_copy_functions<OctreePointColorLeafNode>(
266 octree_point_color_leaf_node);
269 py::class_<Octree, PyGeometry<Octree>, std::shared_ptr<Octree>,
ccHObject>
270 octree(m,
"Octree",
"Octree datastructure.");
271 py::detail::bind_default_constructor<Octree>(
octree);
272 py::detail::bind_copy_functions<Octree>(
octree);
273 octree.def(py::init([](
size_t max_depth) {
return new Octree(max_depth); }),
275 .def(py::init([](
size_t max_depth,
const Eigen::Vector3d &origin,
279 "max_depth"_a,
"origin"_a,
"size"_a)
282 std::ostringstream repr;
283 repr <<
"Octree with ";
284 repr <<
"origin: [" <<
octree.origin_(0) <<
", "
287 repr <<
", size: " <<
octree.size_;
288 repr <<
", max_depth: " <<
octree.max_depth_;
291 .def(
"insert_point", &Octree::InsertPoint,
"point"_a,
"f_init"_a,
292 "f_update"_a,
"fi_init"_a =
nullptr,
"fi_update"_a =
nullptr,
293 "Insert a point to the octree.")
295 py::overload_cast<
const std::function<
bool(
296 const std::shared_ptr<OctreeNode> &,
297 const std::shared_ptr<OctreeNodeInfo> &)> &>(
298 &Octree::Traverse, py::const_),
300 "DFS traversal of the octree from the root, with a "
301 "callback function f being called for each node.")
302 .def(
"locate_leaf_node", &Octree::LocateLeafNode,
"point"_a,
303 "Returns leaf OctreeNode and OctreeNodeInfo where the query"
304 "point should reside.")
305 .def_static(
"is_point_in_bound", &Octree::IsPointInBound,
"point"_a,
306 "origin"_a,
"size"_a,
307 "Return true if point within bound, that is, origin<= "
308 "point < origin + size")
309 .def(
"convert_from_point_cloud", &Octree::ConvertFromPointCloud,
310 "point_cloud"_a,
"size_expand"_a = 0.01,
311 "Convert octree from point cloud.")
312 .def(
"to_voxel_grid", &Octree::ToVoxelGrid,
"Convert to VoxelGrid.")
313 .def(
"create_from_voxel_grid", &Octree::CreateFromVoxelGrid,
315 "Convert from VoxelGrid.")
316 .def_readwrite(
"root_node", &Octree::root_node_,
317 "OctreeNode: The root octree node.")
318 .def_readwrite(
"origin", &Octree::origin_,
319 "(3, 1) float numpy array: Global min bound "
320 "(include). A point is within bound iff origin <= "
321 "point < origin + size.")
323 "float: Outer bounding box edge size for the whole "
324 "octree. A point is within bound iff origin <= "
325 "point < origin + size.")
326 .def_readwrite(
"max_depth", &Octree::max_depth_,
327 "int: Maximum depth of the octree. The depth is "
328 "defined as the distance from the deepest leaf node "
329 "to root. A tree with only the root node has depth "
344 m,
"Octree",
"create_from_voxel_grid",
345 {{
"voxel_grid",
"geometry.VoxelGrid: The source voxel grid."}});
Hierarchical CLOUDVIEWER Object.
OctreeNode's information.
double size_
Size of the node.
Eigen::Vector3d origin_
Origin coordinate of the node.
size_t depth_
Depth of the node to the root. The root is of depth 0.
The base class for octree node.
void ClassMethodDocInject(py::module &pybind_module, const std::string &class_name, const std::string &function_name, const std::unordered_map< std::string, std::string > &map_parameter_body_docs)
void pybind_octree_methods(py::module &m)
static const std::unordered_map< std::string, std::string > map_octree_argument_docstrings
void pybind_octree(py::module &m)
Generic file read and write utility for python interface.