11 #include <json/json.h>
13 #include <Eigen/Dense>
15 #include <unordered_map>
17 #include "VoxelGrid.h"
30 std::string class_name = value.get(
"class_name",
"").asString();
31 std::shared_ptr<OctreeNode> node =
nullptr;
32 if (value != Json::nullValue && class_name !=
"") {
33 if (class_name ==
"OctreeInternalNode") {
34 node = std::make_shared<OctreeInternalNode>();
35 }
else if (class_name ==
"OctreeInternalPointNode") {
36 node = std::make_shared<OctreeInternalPointNode>();
37 }
else if (class_name ==
"OctreeColorLeafNode") {
38 node = std::make_shared<OctreeColorLeafNode>();
39 }
else if (class_name ==
"OctreePointColorLeafNode") {
40 node = std::make_shared<OctreePointColorLeafNode>();
46 if (node !=
nullptr) {
47 bool convert_success = node->ConvertFromJsonValue(value);
48 if (!convert_success) {
55 std::shared_ptr<OctreeNodeInfo> OctreeInternalNode::GetInsertionNodeInfo(
56 const std::shared_ptr<OctreeNodeInfo>& node_info,
57 const Eigen::Vector3d& point) {
60 "Internal error: cannot insert to child since point not in "
61 "parent node bound.");
64 double child_size = node_info->size_ / 2.0;
65 size_t x_index = point(0) < node_info->origin_(0) + child_size ? 0 : 1;
66 size_t y_index = point(1) < node_info->origin_(1) + child_size ? 0 : 1;
67 size_t z_index = point(2) < node_info->origin_(2) + child_size ? 0 : 1;
68 size_t child_index = x_index + y_index * 2 + z_index * 4;
69 Eigen::Vector3d child_origin =
70 node_info->origin_ + Eigen::Vector3d(x_index * child_size,
72 z_index * child_size);
73 auto child_node_info = std::make_shared<OctreeNodeInfo>(
74 child_origin, child_size, node_info->depth_ + 1, child_index);
75 return child_node_info;
78 std::function<std::shared_ptr<OctreeInternalNode>()>
79 OctreeInternalNode::GetInitFunction() {
80 return []() -> std::shared_ptr<geometry::OctreeInternalNode> {
81 return std::make_shared<geometry::OctreeInternalNode>();
85 std::function<void(std::shared_ptr<OctreeInternalNode>)>
86 OctreeInternalNode::GetUpdateFunction() {
87 return [](std::shared_ptr<geometry::OctreeInternalNode> node) ->
void {};
90 bool OctreeInternalNode::ConvertToJsonValue(
Json::Value& value)
const {
92 value[
"class_name"] =
"OctreeInternalNode";
93 value[
"children"] = Json::arrayValue;
94 value[
"children"].resize(8);
95 for (
int cid = 0; cid < 8; ++cid) {
96 if (children_[cid] ==
nullptr) {
97 value[
"children"][Json::ArrayIndex(cid)] = Json::objectValue;
99 rc = rc && children_[cid]->ConvertToJsonValue(
100 value[
"children"][Json::ArrayIndex(cid)]);
106 bool OctreeInternalNode::ConvertFromJsonValue(
const Json::Value& value) {
107 if (!value.isObject()) {
109 "ConvertFromJsonValue read JSON failed: unsupported json "
113 std::string class_name = value.get(
"class_name",
"").asString();
114 if (class_name !=
"OctreeInternalNode") {
119 for (
int cid = 0; cid < 8; ++cid) {
120 const auto& child_value = value[
"children"][Json::ArrayIndex(cid)];
126 std::function<std::shared_ptr<OctreeInternalNode>()>
127 OctreeInternalPointNode::GetInitFunction() {
128 return []() -> std::shared_ptr<geometry::OctreeInternalNode> {
129 return std::make_shared<geometry::OctreeInternalPointNode>();
133 std::function<void(std::shared_ptr<OctreeInternalNode>)>
134 OctreeInternalPointNode::GetUpdateFunction(
size_t idx) {
137 return [idx](std::shared_ptr<geometry::OctreeInternalNode> node) ->
void {
138 if (
auto internal_point_node = std::dynamic_pointer_cast<
139 geometry::OctreeInternalPointNode>(node)) {
140 internal_point_node->indices_.push_back(idx);
143 "Internal error: internal node must be "
144 "OctreeInternalPointNode");
149 bool OctreeInternalPointNode::ConvertToJsonValue(
Json::Value& value)
const {
152 value[
"class_name"] =
"OctreeInternalPointNode";
153 value[
"children"] = Json::arrayValue;
154 value[
"children"].resize(8);
155 for (
int cid = 0; cid < 8; ++cid) {
156 if (children_[cid] ==
nullptr) {
157 value[
"children"][Json::ArrayIndex(cid)] = Json::objectValue;
159 rc = rc && children_[cid]->ConvertToJsonValue(
160 value[
"children"][Json::ArrayIndex(cid)]);
163 value[
"indices"].clear();
164 for (
size_t idx : indices_) {
165 value[
"indices"].append(
static_cast<Json::UInt
>(idx));
170 bool OctreeInternalPointNode::ConvertFromJsonValue(
const Json::Value& value) {
172 if (!value.isObject()) {
174 "ConvertFromJsonValue read JSON failed: unsupported json "
178 std::string class_name = value.get(
"class_name",
"").asString();
179 if (class_name !=
"OctreeInternalPointNode") {
185 for (
int cid = 0; cid < 8; ++cid) {
186 const auto& child_value = value[
"children"][Json::ArrayIndex(cid)];
189 indices_.reserve(value[
"indices"].
size());
190 for (
const auto& v : value[
"indices"]) {
191 indices_.push_back(v.asUInt());
196 std::function<std::shared_ptr<OctreeLeafNode>()>
198 return []() -> std::shared_ptr<geometry::OctreeLeafNode> {
199 return std::make_shared<geometry::OctreeColorLeafNode>();
203 std::function<void(std::shared_ptr<OctreeLeafNode>)>
207 return [
color](std::shared_ptr<geometry::OctreeLeafNode> node) ->
void {
208 if (
auto color_leaf_node =
209 std::dynamic_pointer_cast<geometry::OctreeColorLeafNode>(
211 color_leaf_node->color_ =
color;
214 "Internal error: leaf node must be OctreeColorLeafNode");
220 auto cloned_node = std::make_shared<OctreeColorLeafNode>();
221 cloned_node->color_ =
color_;
230 }
catch (
const std::exception&) {
236 value[
"class_name"] =
"OctreeColorLeafNode";
241 if (value.isObject() ==
false) {
243 "OctreeColorLeafNode read JSON failed: unsupported json "
247 if (value.get(
"class_name",
"") !=
"OctreeColorLeafNode") {
253 std::function<std::shared_ptr<OctreeLeafNode>()>
255 return []() -> std::shared_ptr<geometry::OctreeLeafNode> {
256 return std::make_shared<geometry::OctreePointColorLeafNode>();
260 std::function<void(std::shared_ptr<OctreeLeafNode>)>
262 const Eigen::Vector3d&
color) {
266 color](std::shared_ptr<geometry::OctreeLeafNode> node) ->
void {
267 if (
auto point_color_leaf_node = std::dynamic_pointer_cast<
270 point_color_leaf_node);
271 point_color_leaf_node->indices_.push_back(idx);
274 "Internal error: leaf node must be "
275 "OctreePointColorLeafNode");
281 auto cloned_node = std::make_shared<OctreePointColorLeafNode>();
282 cloned_node->color_ =
color_;
292 return this->
color_.isApprox(that_point_color_node.
color_) &&
293 this->indices_.size() == that_point_color_node.
indices_.size() &&
294 this->indices_ == that_point_color_node.
indices_;
295 }
catch (
const std::exception&) {
301 value[
"class_name"] =
"OctreePointColorLeafNode";
303 value[
"indices"].clear();
305 value[
"indices"].append(
static_cast<Json::UInt
>(idx));
311 if (!value.isObject()) {
313 "OctreePointColorLeafNode read JSON failed: unsupported json "
317 if (value.get(
"class_name",
"") !=
"OctreePointColorLeafNode") {
322 for (
const auto& v : value[
"indices"]) {
330 origin_(src_octree.origin_),
332 max_depth_(src_octree.max_depth_) {
334 std::unordered_map<std::shared_ptr<OctreeNode>, std::shared_ptr<OctreeNode>>
337 [&map_src_to_dst_node](
338 const std::shared_ptr<OctreeNode>& src_node,
339 const std::shared_ptr<OctreeNodeInfo>& src_node_info)
341 if (
auto src_internal_node =
342 std::dynamic_pointer_cast<OctreeInternalNode>(src_node)) {
343 auto dst_internal_node = std::make_shared<OctreeInternalNode>();
344 map_src_to_dst_node[src_internal_node] = dst_internal_node;
345 }
else if (
auto src_leaf_node =
346 std::dynamic_pointer_cast<OctreeLeafNode>(
348 map_src_to_dst_node[src_leaf_node] = src_leaf_node->Clone();
358 [&map_src_to_dst_node](
359 const std::shared_ptr<OctreeNode>& src_node,
360 const std::shared_ptr<OctreeNodeInfo>& src_node_info)
362 if (
auto src_internal_node =
363 std::dynamic_pointer_cast<OctreeInternalNode>(src_node)) {
364 auto dst_internal_node =
365 std::dynamic_pointer_cast<OctreeInternalNode>(
366 map_src_to_dst_node.at(src_internal_node));
367 for (
size_t child_index = 0; child_index < 8; child_index++) {
368 auto src_child_node = src_internal_node->children_[child_index];
369 if (src_child_node !=
nullptr) {
370 auto dst_child_node =
371 map_src_to_dst_node.at(src_child_node);
372 dst_internal_node->children_[child_index] = dst_child_node;
395 std::unordered_map<std::shared_ptr<OctreeNode>,
size_t> map_node_to_id;
396 std::unordered_map<size_t, std::shared_ptr<OctreeNode>> map_id_to_node;
398 auto f_assign_node_id =
399 [&map_node_to_id, &map_id_to_node, &next_id](
400 const std::shared_ptr<OctreeNode>& node,
401 const std::shared_ptr<OctreeNodeInfo>& node_info) ->
bool {
402 map_node_to_id[node] = next_id;
403 map_id_to_node[next_id] = node;
408 map_node_to_id.clear();
409 map_id_to_node.clear();
412 std::unordered_map<std::shared_ptr<OctreeNode>,
size_t>
413 this_map_node_to_id = map_node_to_id;
414 std::unordered_map<size_t, std::shared_ptr<OctreeNode>>
415 this_map_id_to_node = map_id_to_node;
416 size_t num_nodes = next_id;
418 map_node_to_id.clear();
419 map_id_to_node.clear();
422 std::unordered_map<std::shared_ptr<OctreeNode>,
size_t>
423 that_map_node_to_id = map_node_to_id;
424 std::unordered_map<size_t, std::shared_ptr<OctreeNode>>
425 that_map_id_to_node = map_id_to_node;
427 rc = rc && this_map_node_to_id.size() == num_nodes &&
428 that_map_node_to_id.size() == num_nodes &&
429 this_map_id_to_node.size() == num_nodes &&
430 that_map_id_to_node.size() == num_nodes;
436 for (
size_t id = 0;
id < num_nodes; ++id) {
437 std::shared_ptr<OctreeNode> this_node = this_map_id_to_node.at(
id);
438 std::shared_ptr<OctreeNode> that_node = that_map_id_to_node.at(
id);
440 auto is_same_node_type =
false;
441 auto this_internal_node =
442 std::dynamic_pointer_cast<OctreeInternalNode>(this_node);
443 auto that_internal_node =
444 std::dynamic_pointer_cast<OctreeInternalNode>(that_node);
445 if (this_internal_node !=
nullptr && that_internal_node !=
nullptr) {
446 is_same_node_type =
true;
447 for (
size_t child_index = 0; child_index < 8; child_index++) {
448 const std::shared_ptr<OctreeNode>& this_child =
449 this_internal_node->children_[child_index];
450 int this_child_id = -1;
451 if (this_child !=
nullptr) {
452 this_child_id = int(this_map_node_to_id.at(this_child));
454 const std::shared_ptr<OctreeNode>& that_child =
455 that_internal_node->children_[child_index];
456 int that_child_id = -1;
457 if (that_child !=
nullptr) {
458 that_child_id = int(that_map_node_to_id.at(that_child));
460 rc = rc && this_child_id == that_child_id;
464 auto this_leaf_node =
465 std::dynamic_pointer_cast<OctreeLeafNode>(this_node);
466 auto that_leaf_node =
467 std::dynamic_pointer_cast<OctreeLeafNode>(that_node);
468 if (this_leaf_node !=
nullptr && that_leaf_node !=
nullptr) {
469 is_same_node_type =
true;
470 rc = rc && (*this_leaf_node) == (*that_leaf_node);
473 rc = rc && is_same_node_type;
493 return Eigen::Vector3d::Zero();
501 return Eigen::Vector3d::Zero();
540 const Eigen::Vector3d& center) {
546 double size_expand) {
547 if (size_expand > 1 || size_expand < 0) {
553 Eigen::Array3d min_bound = point_cloud.
GetMinBound();
554 Eigen::Array3d max_bound = point_cloud.
GetMaxBound();
555 Eigen::Array3d center = (min_bound + max_bound) / 2;
556 Eigen::Array3d half_sizes = center - min_bound;
557 double max_half_size = half_sizes.maxCoeff();
558 origin_ = min_bound.min(center - max_half_size);
559 if (max_half_size == 0) {
562 size_ = max_half_size * 2 * (1 + size_expand);
567 for (
size_t idx = 0; idx < point_cloud.
size(); idx++) {
570 : Eigen::Vector3d::Zero();
574 OctreeInternalPointNode::GetInitFunction(),
575 OctreeInternalPointNode::GetUpdateFunction(idx));
580 const Eigen::Vector3d& point,
581 const std::function<std::shared_ptr<OctreeLeafNode>()>& fl_init,
582 const std::function<
void(std::shared_ptr<OctreeLeafNode>)>& fl_update,
583 const std::function<std::shared_ptr<OctreeInternalNode>()>& fi_init,
584 const std::function<
void(std::shared_ptr<OctreeInternalNode>)>&
587 auto _fi_init = fi_init;
588 if (_fi_init ==
nullptr) {
589 _fi_init = OctreeInternalNode::GetInitFunction();
591 auto _fi_update = fi_update;
592 if (_fi_update ==
nullptr) {
593 _fi_update = OctreeInternalNode::GetUpdateFunction();
603 auto root_node_info =
606 InsertPointRecurse(
root_node_, root_node_info, point, fl_init, fl_update,
607 _fi_init, _fi_update);
610 void Octree::InsertPointRecurse(
611 const std::shared_ptr<OctreeNode>& node,
612 const std::shared_ptr<OctreeNodeInfo>& node_info,
613 const Eigen::Vector3d& point,
614 const std::function<std::shared_ptr<OctreeLeafNode>()>& fl_init,
615 const std::function<
void(std::shared_ptr<OctreeLeafNode>)>& fl_update,
616 const std::function<std::shared_ptr<OctreeInternalNode>()>& fi_init,
617 const std::function<
void(std::shared_ptr<OctreeInternalNode>)>&
619 if (!
IsPointInBound(point, node_info->origin_, node_info->size_)) {
625 if (
auto leaf_node = std::dynamic_pointer_cast<OctreeLeafNode>(node)) {
626 fl_update(leaf_node);
629 "Internal error: leaf node must be OctreeLeafNode");
632 if (
auto internal_node =
633 std::dynamic_pointer_cast<OctreeInternalNode>(node)) {
635 fi_update(internal_node);
638 std::shared_ptr<OctreeNodeInfo> child_node_info =
639 internal_node->GetInsertionNodeInfo(node_info, point);
642 size_t child_index = child_node_info->child_index_;
643 if (internal_node->children_[child_index] ==
nullptr) {
645 internal_node->children_[child_index] = fl_init();
647 internal_node->children_[child_index] = fi_init();
652 InsertPointRecurse(internal_node->children_[child_index],
653 child_node_info, point, fl_init, fl_update,
657 "Internal error: internal node must be "
658 "OctreeInternalNode");
664 const Eigen::Vector3d&
origin,
665 const double&
size) {
666 bool rc = (Eigen::Array3d(
origin) <= Eigen::Array3d(point)).all() &&
667 (Eigen::Array3d(point) < Eigen::Array3d(
origin) +
size).all();
672 const std::function<
bool(
const std::shared_ptr<OctreeNode>&,
673 const std::shared_ptr<OctreeNodeInfo>&)>& f) {
676 std::make_shared<OctreeNodeInfo>(
origin_,
size_, 0, 0), f);
680 const std::function<
bool(
const std::shared_ptr<OctreeNode>&,
681 const std::shared_ptr<OctreeNodeInfo>&)>& f)
685 std::make_shared<OctreeNodeInfo>(
origin_,
size_, 0, 0), f);
688 void Octree::TraverseRecurse(
689 const std::shared_ptr<OctreeNode>& node,
690 const std::shared_ptr<OctreeNodeInfo>& node_info,
691 const std::function<
bool(
const std::shared_ptr<OctreeNode>&,
692 const std::shared_ptr<OctreeNodeInfo>&)>& f) {
693 if (node ==
nullptr) {
695 }
else if (
auto internal_node =
696 std::dynamic_pointer_cast<OctreeInternalNode>(node)) {
698 if (f(internal_node, node_info))
return;
700 double child_size = node_info->size_ / 2.0;
702 for (
size_t child_index = 0; child_index < 8; ++child_index) {
703 size_t x_index = child_index % 2;
704 size_t y_index = (child_index / 2) % 2;
705 size_t z_index = (child_index / 4) % 2;
707 auto child_node = internal_node->children_[child_index];
708 Eigen::Vector3d child_node_origin =
709 node_info->origin_ + Eigen::Vector3d(
double(x_index),
713 auto child_node_info = std::make_shared<OctreeNodeInfo>(
714 child_node_origin, child_size, node_info->depth_ + 1,
716 TraverseRecurse(child_node, child_node_info, f);
718 }
else if (
auto leaf_node =
719 std::dynamic_pointer_cast<OctreeLeafNode>(node)) {
720 f(leaf_node, node_info);
726 std::pair<std::shared_ptr<OctreeLeafNode>, std::shared_ptr<OctreeNodeInfo>>
728 std::shared_ptr<OctreeLeafNode> target_leaf_node =
nullptr;
729 std::shared_ptr<OctreeNodeInfo> target_leaf_node_info =
nullptr;
730 auto f_locate_leaf_node =
731 [&target_leaf_node, &target_leaf_node_info, &point](
732 const std::shared_ptr<OctreeNode>& node,
733 const std::shared_ptr<OctreeNodeInfo>& node_info) ->
bool {
734 bool skip_children =
false;
735 if (
IsPointInBound(point, node_info->origin_, node_info->size_)) {
737 std::dynamic_pointer_cast<OctreeLeafNode>(node)) {
738 target_leaf_node = leaf_node;
739 target_leaf_node_info = node_info;
742 skip_children =
true;
744 return skip_children;
751 auto voxel_grid = std::make_shared<geometry::VoxelGrid>();
752 voxel_grid->CreateFromOctree(*
this);
758 value[
"class_name"] =
"Octree";
759 value[
"size"] =
size_;
763 value[
"tree"] = Json::objectValue;
765 rc = rc &&
root_node_->ConvertToJsonValue(value[
"tree"]);
771 if (value.isObject() ==
false) {
773 "Octree read JSON failed: unsupported json format.");
776 if (value.get(
"class_name",
"") !=
"Octree") {
783 size_ = value.get(
"size", 0.0).asDouble();
784 max_depth_ = value.get(
"max_depth", 0).asInt64();
794 double half_voxel_size = voxel_grid.
voxel_size_ / 2.;
795 for (
const auto& voxel_iter : voxel_grid.
voxels_) {
797 Eigen::Vector3d mid_point = half_voxel_size +
origin_.array() +
virtual bool IsEmpty() const override
Hierarchical CLOUDVIEWER Object.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
virtual Eigen::Vector3d GetMinBound() const override
Returns min bounds for geometry coordinates.
bool hasColors() const override
Returns whether colors are enabled or not.
Eigen::Vector3d getEigenColor(size_t index) const
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
const Vector3Tpl< T > & maxCorner() const
Returns max corner (const)
void setValidity(bool state)
Sets bonding box validity.
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
unsigned size() const override
Eigen::Vector3d getEigenPoint(size_t index) const
OctreeColorLeafNode class is an OctreeLeafNode containing color.
static std::function< std::shared_ptr< OctreeLeafNode >)> GetInitFunction()
Get lambda function for initializing OctreeLeafNode.
static std::function< void(std::shared_ptr< OctreeLeafNode >)> GetUpdateFunction(const Eigen::Vector3d &color)
Get lambda function for updating OctreeLeafNode.
std::shared_ptr< OctreeLeafNode > Clone() const override
Clone this OctreeLeafNode.
bool operator==(const OctreeLeafNode &other) const override
bool ConvertFromJsonValue(const Json::Value &value) override
bool ConvertToJsonValue(Json::Value &value) const override
OctreeLeafNode base class.
static std::shared_ptr< OctreeNode > ConstructFromJsonValue(const Json::Value &value)
Factory function to construct an OctreeNode by parsing the json value.
OctreePointColorLeafNode class is an OctreeColorLeafNode containing a list of indices corresponding t...
std::vector< size_t > indices_
Associated point indices with this node.
static std::function< void(std::shared_ptr< OctreeLeafNode >)> GetUpdateFunction(size_t index, const Eigen::Vector3d &color)
Get lambda function for updating OctreeLeafNode.
bool ConvertToJsonValue(Json::Value &value) const override
static std::function< std::shared_ptr< OctreeLeafNode >)> GetInitFunction()
Get lambda function for initializing OctreeLeafNode.
bool ConvertFromJsonValue(const Json::Value &value) override
std::shared_ptr< OctreeLeafNode > Clone() const override
Clone this OctreeLeafNode.
bool operator==(const OctreeLeafNode &other) const override
virtual Octree & Transform(const Eigen::Matrix4d &transformation) override
Apply transformation (4x4 matrix) to the geometry coordinates.
void CreateFromVoxelGrid(const geometry::VoxelGrid &voxel_grid)
Convert from voxel grid.
Octree(const char *name="Octree2")
Default Constructor.
std::shared_ptr< geometry::VoxelGrid > ToVoxelGrid() const
Convert to VoxelGrid.
static bool IsPointInBound(const Eigen::Vector3d &point, const Eigen::Vector3d &origin, const double &size)
Return true if point within bound, that is, origin <= point < origin + size.
virtual ecvOrientedBBox GetOrientedBoundingBox() const override
bool ConvertToJsonValue(Json::Value &value) const override
void ConvertFromPointCloud(const ccPointCloud &point_cloud, double size_expand=0.01)
Convert octree from point cloud.
virtual ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
virtual Octree & Scale(const double s, const Eigen::Vector3d ¢er) override
Apply scaling to the geometry coordinates. Given a scaling factor , and center , a given point is tr...
virtual Eigen::Vector3d GetMinBound() const override
Returns min bounds for geometry coordinates.
bool operator==(const Octree &other) const
Returns true if the Octree is completely the same, used for testing.
virtual ccBBox GetAxisAlignedBoundingBox() const override
Returns an axis-aligned bounding box of the geometry.
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
virtual bool IsEmpty() const override
void InsertPoint(const Eigen::Vector3d &point, const std::function< std::shared_ptr< OctreeLeafNode >()> &fl_init, const std::function< void(std::shared_ptr< OctreeLeafNode >)> &fl_update, const std::function< std::shared_ptr< OctreeInternalNode >()> &fi_init=nullptr, const std::function< void(std::shared_ptr< OctreeInternalNode >)> &fi_update=nullptr)
Insert a point to the octree.
virtual Octree & Translate(const Eigen::Vector3d &translation, bool relative=true) override
Apply translation to the geometry coordinates.
std::pair< std::shared_ptr< OctreeLeafNode >, std::shared_ptr< OctreeNodeInfo > > LocateLeafNode(const Eigen::Vector3d &point) const
Returns leaf OctreeNode and OctreeNodeInfo where the querypoint should reside.
std::shared_ptr< OctreeNode > root_node_
Root of the octree.
void Traverse(const std::function< bool(const std::shared_ptr< OctreeNode > &, const std::shared_ptr< OctreeNodeInfo > &)> &f)
DFS traversal of Octree from the root, with callback function called for each node.
virtual Octree & Rotate(const Eigen::Matrix3d &R, const Eigen::Vector3d ¢er) override
Apply rotation to the geometry coordinates and normals. Given a rotation matrix , and center ,...
virtual Eigen::Vector3d GetCenter() const override
Returns the center of the geometry coordinates.
bool ConvertFromJsonValue(const Json::Value &value) override
VoxelGrid is a collection of voxels which are aligned in grid.
std::unordered_map< Eigen::Vector3i, Voxel, cloudViewer::utility::hash_eigen< Eigen::Vector3i > > voxels_
Voxels contained in voxel grid.
double voxel_size_
Size of the voxel.
Eigen::Vector3d origin_
Coorindate of the origin point.
virtual Eigen::Vector3d GetMaxBound() const override
Returns max bounds for geometry coordinates.
Base Voxel class, containing grid id and color.
Eigen::Vector3i grid_index_
Grid coordinate index of the voxel.
Eigen::Vector3d color_
Color of the voxel.
static bool EigenVector3dFromJsonArray(Eigen::Vector3d &vec, const Json::Value &value)
static bool EigenVector3dToJsonArray(const Eigen::Vector3d &vec, Json::Value &value)
static ecvOrientedBBox CreateFromAxisAlignedBoundingBox(const ccBBox &aabox)
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
Generic file read and write utility for python interface.
static vtkPVTrivialProducerStaticInternal Value