Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Loading...
Searching...
No Matches
DTree.h
Go to the documentation of this file.
1
29#pragma once
30
32
33#include <algorithm>
34
35namespace ogdf {
36namespace energybased {
37namespace dtree {
38
40template<typename IntType, int Dim>
41class DTree {
42public:
44 static constexpr int MaxNumChildrenPerNode = (1 << Dim);
45
47 explicit DTree(int numPoints)
48 : m_maxLevel((sizeof(IntType) << 3) + 1), m_numPoints(0), m_rootIndex(-1) {
50 }
51
54
56 struct Point {
57 IntType x[Dim];
58 };
59
61 struct MortonEntry {
62 IntType mortonNr[Dim];
63 int ref;
64
66 bool operator<(const MortonEntry& other) const {
68 }
69
71 bool operator==(const MortonEntry& other) const {
73 }
74 };
75
77 struct Node {
78 // quadtree related stuff
79 int level;
80 int next;
85 };
86
88 inline const Node& node(int i) const { return m_nodes[i]; };
89
91 inline Node& node(int i) { return m_nodes[i]; };
92
94 inline int numChilds(int i) const { return m_nodes[i].numChilds; };
95
97 inline int child(int i, int j) const { return m_nodes[i].child[j]; };
98
100 inline int numPoints(int i) const { return m_nodes[i].numPoints; };
101
103 inline int point(int i, int j) const { return m_mortonOrder[m_nodes[i].firstPoint + j].ref; };
104
106 void setPoint(int i, int d, IntType value);
107
109 inline int numPoints() const { return m_numPoints; };
110
112 inline int maxNumNodes() const { return m_numPoints * 2; };
113
115 const Point& point(int i) const { return m_points[i]; }
116
118 void prepareMortonOrder();
119
121 void sortMortonNumbers();
122
124 void prepareNodeLayer();
125
127 inline void mergeWithNext(int curr);
128
130 inline void adjustPointInfo(int curr);
131
133 int linkNodes(int curr, int maxLevel);
134
136 void linkNodes();
137
139 void build();
140
142 int countPoints(int curr) const;
143
145 int countPoints() const { return countPoints(m_rootIndex); };
146
148 int rootIndex() const { return m_rootIndex; };
149
150private:
152 void allocate(int n);
153
155 void deallocate();
156
158 Point* m_points = nullptr;
161 Node* m_nodes = nullptr;
163};
164
166template<typename IntType, int Dim>
168 m_numPoints = n;
169 m_points = new Point[m_numPoints];
170 m_mortonOrder = new MortonEntry[m_numPoints];
171 m_nodes = new Node[m_numPoints * 2];
172};
173
175template<typename IntType, int Dim>
177 delete[] m_points;
178 delete[] m_mortonOrder;
179 delete[] m_nodes;
180};
181
182template<typename IntType, int Dim>
183void DTree<IntType, Dim>::setPoint(int i, int d, IntType value) {
184 // set i-th point d coord to value
185 m_points[i].x[d] = value;
186}
187
189template<typename IntType, int Dim>
191 // loop over the point order
192 for (int i = 0; i < m_numPoints; i++) {
193 // set i's ref to i
194 m_mortonOrder[i].ref = i;
195
196 // generate the morton number by interleaving the bits
197 interleaveBits<IntType, Dim>(m_points[i].x, m_mortonOrder[i].mortonNr);
198 }
199}
200
202template<typename IntType, int Dim>
204 // just sort them
205 std::sort(m_mortonOrder, m_mortonOrder + m_numPoints);
206}
207
209template<typename IntType, int Dim>
211 Node* leafLayer = m_nodes;
212 Node* innerLayer = m_nodes + m_numPoints;
213
214#if 0
215 int last = 0;
216#endif
217 for (int i = 0; i < m_numPoints;) {
218 Node& leaf = leafLayer[i];
220 // i represents the current node on both layers
221 int j = i + 1;
222
223 // find the next morton number that differs or stop when j is equal to m_numPoints
224 while ((j < m_numPoints) && (m_mortonOrder[i] == m_mortonOrder[j])) {
225 j++;
226 }
227 // j is the index of the next cell (node)
228
229 // init the node on the leaf layer
230 leaf.firstPoint = i; //< node sits above the first point of the cell
231 leaf.numPoints =
232 j - i; //< number of points with equal morton numbers (number of points in grid cell)
233 leaf.numChilds = 0; //< it's a leaf
234 leaf.level = 0; //< it's a leaf
235 leaf.next = j; //< this leaf hasnt been created yet but we use indices so its ok
236
237 if (j < m_numPoints) {
238 // Note: the n-th inner node is not needed because we only need n-1 inner nodes to cover n leaves
239 // if we reach the n-1-th inner node, the variable last is set for the last time
240#if 0
241 last = i;
242#endif
243 // init the node on the inner node layer
244 innerNode.child[0] = i; //< node sits above the first leaf
245 innerNode.child[1] = j; //< this leaf hasnt been created yet but we use indices so its ok
246 innerNode.numChilds = 2; //< every inner node covers two leaves in the beginning
247 innerNode.level = lowestCommonAncestorLevel<IntType, Dim>(m_mortonOrder[i].mortonNr,
248 m_mortonOrder[j].mortonNr);
249 innerNode.next = m_numPoints + j; // the inner node layer is shifted by n
250 } else {
251 // no next for the last
252 innerLayer[i].next = 0;
253 // this is important to make the recursion stop
254 innerLayer[i].level = m_maxLevel + 1;
255 }
256
257 // advance to the next cell
258 i = j;
259 };
260 // here we set the successor of the n-1-th inner node to zero to avoid dealing with the n-th inner node
261#if 0
262 innerLayer[last].next = 0;
263#endif
264};
265
267template<typename IntType, int Dim>
269 int next = node(curr).next;
270 // Cool: since we never touched node(next) before
271 // it is still linked to only two leaves,
272 node(curr).child[node(curr).numChilds++] = node(next).child[1];
273
274 // thus we don't need this ugly loop:
275 // for (int i=1; i<node(next).numChilds; i++)
276 // node(curr).child[node(curr).numChilds++] = node(next).child[i];
277 node(curr).next = node(next).next;
278};
279
280template<typename IntType, int Dim>
282 // adjust the first such that it matched the first child
283 node(curr).firstPoint = node(node(curr).child[0]).firstPoint;
284
285 // index of the last child
286 const int lastChild = node(curr).child[node(curr).numChilds - 1];
287
288 // numPoints is lastPoint + 1 - firstPoint
289 node(curr).numPoints =
290 node(lastChild).firstPoint + node(lastChild).numPoints - node(curr).firstPoint;
291}
292
294template<typename IntType, int Dim>
295int DTree<IntType, Dim>::linkNodes(int curr, int maxLevel) {
296 // while the subtree is smaller than maxLevel
297 while (node(curr).next && node(node(curr).next).level < maxLevel) {
298 // get next node in the chain
299 int next = node(curr).next;
300 // First case: same level => merge, discard next
301 if (node(curr).level == node(next).level) {
302 mergeWithNext(curr);
303 } else if (node(curr).level < node(next).level) {
304 // Second case: next is higher => become first child
305 // set the first child of next to the current node
306 node(next).child[0] = curr;
307
308 // adjust the point info of the curr
309 adjustPointInfo(curr);
310
311 // this is the only case where we advance curr
312 curr = next;
313 } else { // Third case: next is smaller => construct a maximal subtree starting with next
314 int r = linkNodes(next, node(curr).level);
315 node(curr).child[node(curr).numChilds - 1] = r;
316 node(curr).next = node(r).next;
317 };
318 };
319 // adjust the point info of the curr
320 adjustPointInfo(curr);
321
322 // we are done with this subtree, return the root
323 return curr;
324};
325
327template<typename IntType, int Dim>
329 m_rootIndex = linkNodes(m_numPoints, m_maxLevel);
330};
331
333template<typename IntType, int Dim>
335 if (m_nodes[curr].numChilds) {
336 int sum = 0;
337 for (int i = 0; i < m_nodes[curr].numChilds; i++) {
338 sum += countPoints(m_nodes[curr].child[i]);
339 };
340
341 return sum;
342 } else {
343 return m_nodes[curr].numPoints;
344 }
345};
346
348template<typename IntType, int Dim>
350 // prepare the array with the morton numbers
351 prepareMortonOrder();
352
353 // sort the morton numbers
354 sortMortonNumbers();
355
356 // prepare the node layer
357 prepareNodeLayer();
358
360 linkNodes();
361};
362
363}
364}
365}
Implentation of the reduced quadtree for Dim dimensions.
Definition DTree.h:41
const Point & point(int i) const
returns the ith point in the input sequence
Definition DTree.h:115
int point(int i, int j) const
returns the index of the jth point covered by i's subtree.
Definition DTree.h:103
void sortMortonNumbers()
Sorts the points by morton number.
Definition DTree.h:203
int m_rootIndex
The index of the root node.
Definition DTree.h:162
int countPoints() const
Just for fun: traverse the tree and count the points in the leaves.
Definition DTree.h:145
void adjustPointInfo(int curr)
used to update the first and numPoints of inner nodes by linkNodes
Definition DTree.h:281
Point * m_points
The input set.
Definition DTree.h:158
static constexpr int MaxNumChildrenPerNode
the maximum number of children per node = 2^d
Definition DTree.h:44
void prepareNodeLayer()
Prepares both the leaf and inner node layer.
Definition DTree.h:210
int maxNumNodes() const
returns the maximum number of nodes (and the max index of a node)
Definition DTree.h:112
Node * m_nodes
Memory for all nodes.
Definition DTree.h:161
void deallocate()
Releases memory.
Definition DTree.h:176
void mergeWithNext(int curr)
Merges curr with next node in the chain (used by linkNodes)
Definition DTree.h:268
int numChilds(int i) const
returns the number of children of node i
Definition DTree.h:94
int numPoints() const
returns the number of points the quadtree contains
Definition DTree.h:109
int numPoints(int i) const
returns the number of points covered by this subtree
Definition DTree.h:100
int m_numPoints
Total number of points.
Definition DTree.h:159
int child(int i, int j) const
returns the index of the j th child of node i
Definition DTree.h:97
void allocate(int n)
Allocates memory for n points.
Definition DTree.h:167
void setPoint(int i, int d, IntType value)
sets the point to the given grid coords
Definition DTree.h:183
const Node & node(int i) const
Just to access the nodes a little bit easier.
Definition DTree.h:88
DTree(int numPoints)
constructor
Definition DTree.h:47
void prepareMortonOrder()
Prepares the morton numbers for sorting.
Definition DTree.h:190
void build()
Does all required steps except the allocate, deallocate, randomPoints.
Definition DTree.h:349
Node & node(int i)
Just to access the nodes a little bit easier.
Definition DTree.h:91
MortonEntry * m_mortonOrder
The order to be sorted.
Definition DTree.h:160
void linkNodes()
The Recursive Bottom-Up Construction (recursion start)
Definition DTree.h:328
int rootIndex() const
returns the index of the root node
Definition DTree.h:148
NodeElement * node
The type of nodes.
Definition Graph_d.h:64
int r[]
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.
The entry in the sorted order for a point.
Definition DTree.h:61
int ref
index in the original point order
Definition DTree.h:63
IntType mortonNr[Dim]
the morton number of the point
Definition DTree.h:62
bool operator<(const MortonEntry &other) const
less comparator for sort
Definition DTree.h:66
bool operator==(const MortonEntry &other) const
equal comparer for the construction algorithm
Definition DTree.h:71
int numChilds
number of children
Definition DTree.h:82
int next
the next node on the same layer (leaf or inner node layer)
Definition DTree.h:80
int firstPoint
the first point in the sorted order covered by this subtree
Definition DTree.h:83
int child[MaxNumChildrenPerNode]
index of the children
Definition DTree.h:81
int level
the level of the node in a complete quadtree
Definition DTree.h:79
int numPoints
the number of points covered by this subtree
Definition DTree.h:84
The point class with integer coords.
Definition DTree.h:56