@@ -37,10 +37,10 @@ struct StaticOctreeNode
3737{
3838 using PointType = Eigen::Matrix<PREC, 3 , 1 >;
3939
40- StaticOctreeNode (const PointType&, PREC );
40+ StaticOctreeNode (const PointType&, OctreeDepthType );
4141
4242 PointType center;
43- PREC scale ;
43+ OctreeDepthType depth ;
4444 OctreeNodeIndex right{ InvalidOctreeNode };
4545 OctreeObjectIndex first{ 0 };
4646 OctreeObjectIndex last{ 0 };
@@ -49,9 +49,9 @@ struct StaticOctreeNode
4949
5050template <class PREC >
5151StaticOctreeNode<PREC>::StaticOctreeNode(const PointType& _center,
52- PREC _scale ) :
52+ OctreeDepthType _depth ) :
5353 center (_center),
54- scale(_scale )
54+ depth(_depth )
5555{
5656}
5757
@@ -95,6 +95,9 @@ class StaticOctree
9595 template <typename PROCESSOR>
9696 void processDepthFirst (PROCESSOR&) const ;
9797
98+ template <typename PROCESSOR>
99+ void processBreadthFirst (PROCESSOR&) const ;
100+
98101 OctreeObjectIndex size () const ;
99102 OctreeNodeIndex nodeCount () const ;
100103
@@ -104,8 +107,14 @@ class StaticOctree
104107private:
105108 using NodeType = detail::StaticOctreeNode<PREC>;
106109
110+ template <typename PROCESSOR>
111+ bool processToDepth (PROCESSOR&, OctreeDepthType) const ;
112+
107113 std::vector<NodeType> m_nodes;
108114 std::vector<OBJ> m_objects;
115+ std::vector<PREC> m_sizes;
116+ OctreeDepthType m_minPopulated{ UINT32_MAX };
117+ OctreeDepthType m_maxDepth{ 0 };
109118
110119 template <class TRAITS , class STORAGE >
111120 friend class DynamicOctree ;
@@ -117,25 +126,69 @@ void
117126StaticOctree<OBJ, PREC>::processDepthFirst(PROCESSOR& processor) const
118127{
119128 OctreeNodeIndex nodeIdx = 0 ;
120- OctreeNodeIndex endIdx = nodeCount ();
129+ const OctreeNodeIndex endIdx = nodeCount ();
121130 while (nodeIdx < endIdx)
122131 {
123132 const NodeType& node = m_nodes[nodeIdx];
124- if (!processor.checkNode (node.center , node.scale , node.brightFactor ))
133+ if (!processor.checkNode (node.center , m_sizes[ node.depth ] , node.brightFactor ))
125134 {
126135 nodeIdx = node.right ;
127136 continue ;
128137 }
129138
130139 for (OctreeObjectIndex idx = node.first ; idx < node.last ; ++idx)
131- {
132140 processor.process (m_objects[idx]);
133- }
134141
135142 ++nodeIdx;
136143 }
137144}
138145
146+ // Simulate a breadth-first search by doing an interative depth-first search,
147+ // starting at the minimum populated depth. The search terminates when no nodes
148+ // at the requested depth are reached.
149+ template <class OBJ , class PREC >
150+ template <typename PROCESSOR>
151+ void
152+ StaticOctree<OBJ, PREC>::processBreadthFirst(PROCESSOR& processor) const
153+ {
154+ for (OctreeDepthType depth = m_minPopulated; depth <= m_maxDepth; ++depth)
155+ {
156+ if (!processToDepth (processor, depth))
157+ break ;
158+ }
159+ }
160+
161+ template <class OBJ , class PREC >
162+ template <typename PROCESSOR>
163+ bool
164+ StaticOctree<OBJ, PREC>::processToDepth(PROCESSOR& processor, OctreeDepthType depth) const
165+ {
166+ OctreeNodeIndex nodeIdx = 0 ;
167+ const OctreeNodeIndex endIdx = nodeCount ();
168+ bool result = false ;
169+ while (nodeIdx < endIdx)
170+ {
171+ const NodeType& node = m_nodes[nodeIdx];
172+ if (!processor.checkNode (node.center , m_sizes[node.depth ], node.brightFactor ))
173+ {
174+ nodeIdx = node.right ;
175+ }
176+ else if (node.depth == depth)
177+ {
178+ result = true ;
179+ for (OctreeObjectIndex idx = node.first ; idx < node.last ; ++idx)
180+ processor.process (m_objects[idx]);
181+ nodeIdx = node.right ;
182+ }
183+ else
184+ {
185+ ++nodeIdx;
186+ }
187+ }
188+
189+ return result;
190+ }
191+
139192template <class OBJ , class PREC >
140193OctreeObjectIndex
141194StaticOctree<OBJ, PREC>::size() const
0 commit comments