geolib2
OctreeNode.cpp
Go to the documentation of this file.
1 #include "geolib/OctreeNode.h"
2 #include "geolib/Octree.h"
3 #include "geolib/Box.h"
4 
5 namespace geo {
6 
7 OctreeNode::OctreeNode(double size, Octree* tree)
8  : size_(size), split_(size_ / 2), occupied_(false), tree_(tree) {
9  for(unsigned int i = 0; i < 8; ++i) {
10  children_[i] = 0;
11  }
12 }
13 
15  : size_(orig.size_), split_(orig.split_), occupied_(orig.occupied_), tree_(tree) {
16  for(unsigned int i = 0; i < 8; ++i) {
17  if (orig.children_[i]) {
18  children_[i] = new OctreeNode(*orig.children_[i], tree);
19  } else {
20  children_[i] = 0;
21  }
22  }
23 }
24 
26  for(unsigned int i = 0; i < 8; ++i) {
27  delete children_[i];
28  }
29 }
30 
31 void OctreeNode::add(const Vector3& p) {
32  //std::cout << p << ", size = " << size_ << std::endl;
33 
34  if (size_ - 1e-10 < tree_->resolution_) {
35  occupied_ = true;
36  return;
37  }
38 
39  int index = 0;
40 
41  double x = p.x;
42  double y = p.y;
43  double z = p.z;
44 
45  if (x > split_) { index += 4; x-= split_; }
46  if (y > split_) { index += 2; y-= split_; }
47  if (z > split_) { index += 1; z-= split_; }
48 
49  if (!children_[index]) {
50  children_[index] = new OctreeNode(size_ / 2, tree_);
51  }
52  children_[index]->add(Vector3(x, y, z));
53 }
54 
55 void OctreeNode::getCubes(std::vector<Box>& cubes, const Vector3& offset) const {
56  if (occupied_) {
57  cubes.push_back(Box(offset, offset + Vector3(size_, size_, size_)));
58  } else {
59  int i = 0;
60  for(int x = 0; x <= 1; ++x) {
61  for(int y = 0; y <= 1; ++y) {
62  for(int z = 0; z <= 1; ++z) {
63  if (children_[i]) {
64  children_[i]->getCubes(cubes, offset + Vector3(split_ * x, split_ * y, split_ * z));
65  }
66  ++i;
67  }
68  }
69  }
70  }
71 }
72 
73 
74 bool OctreeNode::intersect(const Ray& r, float t0, float t1, double& distance, const Vector3& offset) const {
75 
76  //std::cout << r.getOrigin() << ", t0 = " << t0 << ", t1 = " << t1 << " distance = " << distance << std::endl;
77  //std::cout << offset << " - " << offset + Vector3(size_, size_, size_) << std::endl;
78 
79  if (occupied_) {
80  return true;
81  }
82 
83  Vector3 o = r.getOrigin() + t0 * r.getDirection();
84  if (o.x < 0 || o.y < 0 || o.z < 0
85  || o.x > size_ || o.y > size_ || o.z > size_) {
86  return false;
87  }
88 
89  //std::cout << " o = " << o << std::endl;
90 
91  int index = 0;
92 
93  double dx = 0;
94  double dy = 0;
95  double dz = 0;
96 
97  if (o.x >= split_) { index += 4; dx = split_; }
98  if (o.y >= split_) { index += 2; dy = split_; }
99  if (o.z >= split_) { index += 1; dz = split_; }
100 
101  if (children_[index]) {
102  if (children_[index]->intersect(Ray(r.getOrigin() - Vector3(dx, dy, dz), r.getDirection()), t0, t1, distance, offset + Vector3(dx, dy, dz))) {
103  return true;
104  }
105 
106  // is distance already correctly set in this case? If so, no need to calculate it again below
107  }
108 
109  double dist;
110  Box b(Vector3(dx, dy, dz), Vector3(dx + size_ / 2, dy + size_ / 2, dz + size_ / 2));
111  b.intersect(Ray(o, -r.getDirection()), 0, t1 - t0, dist);
112  distance = t0 - dist;
113  return this->intersect(r, distance + tree_->resolution_ * 0.1, t1, distance, offset);
114 }
115 
116 void OctreeNode::raytrace(const Vector3& o, const Vector3& dir, float t0, float t1, const Vector3& offset) {
117  if (t1 < t0) {
118  return;
119  }
120 
121  Vector3 newo = o + t0 * dir;
122  if (newo.x < 0 || newo.y < 0 || newo.z < 0
123  || newo.x > size_ || newo.y > size_ || newo.z > size_) {
124  return;
125  }
126 
127  occupied_ = false;
128 
129  int index = 0;
130 
131  double dx = 0;
132  double dy = 0;
133  double dz = 0;
134 
135  if (newo.x >= split_) { index += 4; dx = split_; }
136  if (newo.y >= split_) { index += 2; dy = split_; }
137  if (newo.z >= split_) { index += 1; dz = split_; }
138 
139  if (children_[index]) {
140  children_[index]->raytrace(o - Vector3(dx, dy, dz), dir, t0, t1, offset + Vector3(dx, dy, dz));
141  }
142 
143  double dist;
144  Box b(Vector3(dx, dy, dz), Vector3(dx + size_ / 2, dy + size_ / 2, dz + size_ / 2));
145  b.intersect(Ray(newo, -dir), 0, t1 - t0, dist);
146  double distance = t0 - dist;
147  this->raytrace(o, dir, distance + tree_->resolution_ * 0.1, t1, offset);
148 }
149 
150 bool OctreeNode::contains(const Vector3& p) const {
151  if (occupied_) {
152  return true;
153  }
154 
155  int index = 0;
156 
157  double x = p.x;
158  double y = p.y;
159  double z = p.z;
160 
161  if (x > split_) { index += 4; x-= split_; }
162  if (y > split_) { index += 2; y-= split_; }
163  if (z > split_) { index += 1; z-= split_; }
164 
165  if (!children_[index]) {
166  return false;
167  } else {
168  return children_[index]->contains(p);
169  }
170 }
171 
172 bool OctreeNode::intersect(const Box& b) const {
173  if (occupied_) {
174  return true;
175  }
176  const Vector3& min = b.getMin();
177  const Vector3& max = b.getMax();
178 
179  int sx = min.x > split_;
180  int ex = max.x > split_;
181 
182  int sy = min.y > split_;
183  int ey = max.y > split_;
184 
185  int sz = min.z > split_;
186  int ez = max.z > split_;
187 
188  for(int x = sx; x <= ex; ++x) {
189  for(int y = sy; y <= ey; ++y) {
190  for(int z = sz; z <= ez; ++z) {
191  int i = 4 * x + 2 * y + z;
192  if (children_[i]) {
193  Vector3 offset(split_ * x, split_ * y, split_ * z);
194  if (children_[i]->intersect(Box(min - offset, max - offset))) {
195  return true;
196  }
197  }
198  }
199  }
200  }
201 
202  return false;
203 }
204 
205 }
geo::Vector3::y
const real & y() const
Definition: matrix.h:32
geo::Vector3
Vec3 Vector3
Definition: datatypes.h:32
geo::OctreeNode
Definition: OctreeNode.h:12
geo::OctreeNode::OctreeNode
OctreeNode(const OctreeNode &orig, Octree *tree)
Definition: OctreeNode.cpp:14
geo::OctreeNode::split_
double split_
Definition: OctreeNode.h:40
geo::OctreeNode::~OctreeNode
virtual ~OctreeNode()
Definition: OctreeNode.cpp:25
geo::Ray::getOrigin
const Vector3 & getOrigin() const
Definition: Ray.h:16
geo
Definition: Box.h:6
geo::OctreeNode::add
void add(const Vector3 &p)
Definition: OctreeNode.cpp:31
std::vector
geo::Box
Definition: Box.h:15
geo::OctreeNode::occupied_
bool occupied_
Definition: OctreeNode.h:44
geo::OctreeNode::tree_
Octree * tree_
Definition: OctreeNode.h:46
std::vector::push_back
T push_back(T... args)
geo::OctreeNode::children_
OctreeNode * children_[8]
Definition: OctreeNode.h:42
geo::OctreeNode::raytrace
void raytrace(const Vector3 &o, const Vector3 &dir, float t0, float t1, const Vector3 &offset)
Definition: OctreeNode.cpp:116
geo::Ray
Definition: Ray.h:10
geo::Vector3
Definition: matrix.h:12
geo::Octree
Definition: Octree.h:12
geo::OctreeNode::getCubes
void getCubes(std::vector< Box > &cubes, const Vector3 &offset) const
Definition: OctreeNode.cpp:55
geo::Vector3::z
const real & z() const
Definition: matrix.h:33
geo::OctreeNode::size_
double size_
Definition: OctreeNode.h:38
b
void b()
OctreeNode.h
geo::Vector3::x
const real & x() const
Definition: matrix.h:31
geo::Ray::getDirection
const Vector3 & getDirection() const
Definition: Ray.h:18
geo::OctreeNode::intersect
bool intersect(const Ray &r, float t0, float t1, double &distance, const Vector3 &offset) const
Definition: OctreeNode.cpp:74
geo::Octree::resolution_
double resolution_
Definition: Octree.h:50
Box.h
Octree.h
geo::OctreeNode::OctreeNode
OctreeNode(double size, Octree *octree)
Definition: OctreeNode.cpp:7
geo::OctreeNode::contains
bool contains(const Vector3 &p) const
Definition: OctreeNode.cpp:150