# DTree A DTree is a generalization of trees that devide space into regular partitions in D dimensions, such as (2D) and Octrees (3D). ### DTrees The regularity of DTrees makes especially suitable for spatial information that is also regular in space such as points in a lattice, because any node in the tree is associated with a specific part of space, and thus unique associated with a point in the lattice. ### Components and Defintions DTrees consists of at least one node, the root node. Each node is of either one of two classes: a leaf-node or a branch-node. A leaf-node contains data, but has no children. A branch-node has children, but contains no data. Every node knows it own depth in the tree. Every node except the root node knows its parent and its own index in the parent, the index being a number between 0 and N. The root node has no parent, and consequently no index. Note that given a node's depth, index in the parent and the parent itself, it is possible to derive its corresponding partition of space. In fact, each node has a unique identifier that indicates its position in the tree based on this information. These identifiers can be used to quickly retrieve nodes from the tree. ## Interface A tree is the holder of the root node. It supports most methods of a node, forwarding them to the root node. Exceptions are the methods to obtain the index or parent of the root node because these don't exist by definition.
    template <typename T, std::size_t D>
    class DTree;
    template <typename T, std::size_t D>
    class DNode;
Asking the root node for its parent or index will throw an exception:
    class NoParentException : public std::exception;
Asking a branch-node for its value will throw an exception:
    class BranchNodeException : public std::exception;
Asking a leaf-node for a child node will throw an exception:
    class LeafNodeException : public std::exception;
Reading a DTree from invalid input:
    class InvalidDTreeXML : public std::exception;
### DTree
      typedef DNode
| The type of the nodes of this tree.
      typedef index_t
| The type of indices in a branch-node.
      static const std::size_t N
| The number of children of a branch-node.
      DTree(const T value)
| Constructor with initial value for the root node. The root node is a leaf-node.
      DNode operator[](const index_t i)
    	throw(LeafNodeException)
| Obtain a child node of the root node. The root node must be a branch-node.
      const DNode operator[](const index_t i) const
    	throw(LeafNodeException)
| Obtain a read-only child node of the root node. The root node must be a branch-node.
      DNode root()
| Obtain the root node.
      operator DNode()
| Implicitly convert the tree to the root node.
      operator const DNode() const
| Implicitly convert the tree to the root node, read-only.
      T& operator()() throw(BranchNodeException)
| Explicitly convert the root node to a reference to the value it holds.
      const T& operator()() const throw(BranchNodeException)
| Explicitly convert the root node to a read-only reference to the value it holds.
      bool isLeaf() const
| Returns true if the root node is a leaf-node.
      operator const T&() const throw(BranchNodeException)
| Implicitly convert the root node into a read-only reference to its value. The root node must be a leaf-node.
      template <typename U>
      void collapse(const U value) throw(LeafNodeException)
| Turn the root node from a branch-node into a leaf-node with the given value, discarding all children.
      void expand() throw(BranchNodeException)
| Expand the root node from a leaf-node into a branch-node. The value of all children will be the current value of the leaf-node.
      template <typename U>
      void expand(const U value) throw(BranchNodeException)
| Expand the root node from a leaf-node into a branch-node. The value of all children will be the given value.
      template <typename It>
      void expand(It first, It last) throw(BranchNodeException)
| Expand the root node from a leaf-node into a branch-node. The value of all children will be read from the first elements of the range first to last.
      std::size_t depth() const
| Return the depth of the tree at the root node, which is by definition zero.
      bool operator==(const DTree &that) const
| Test if two DTrees refer to the same data - not if they actually contain the same data.
      bool operator!=(const DTree &that) const
| Negation of operator==.
      DTree<T, D> clone() const
| Return DTree containg a copy of this tree.
      std::size_t id() const
| Return a unique identifier associated with the root node. By definition, that is zero.
      const DNode retrieve(std::size_t id) const throw (LeafNodeException)
| Return the DNode associated with the unique identifier id. Providing an invalid identifier might cause an exception to be thrown.
      DNode retrieve(std::size_t id) throw (LeafNodeException)
| Return the DNode associated with the unique identifier id. Providing an invalid identifier might cause an exception to be thrown.
### DTree::DNode
      typedef index_t
| The type of indices in a branch-node.
      static const std::size_t N
| The number of children of a branch-node.
      T& operator()() throw(BranchNodeException)
| Explicitly convert a node to a reference to the value it holds.
      const T& operator()() const throw(BranchNodeException)
| Explicitly convert a node to a read-only reference to the value it holds.
      DNode operator[](const index_t i)
    	throw(LeafNodeException)
| Obtain a child node of the node. The node must be a branch-node.
      const DNode operator[](const index_t i) const
    	throw(LeafNodeException)
| Obtain a read-only child node of the node. The node must be a branch-node.
      bool isLeaf() const
| Returns true if the node is a leaf-node.
      template <typename U>
      void collapse(const U value) throw(LeafNodeException)
| Turn the node from a branch-node into a leaf-node with the given value, discarding all children.
      void expand() throw(BranchNodeException)
| Expand a leaf-node into a branch-node. The value of all children will be the current value of the leaf-node.
      template <typename U>
      void expand(const U value) throw(BranchNodeException)
| Expand a leaf-node into a branch-node. The value of all children will be the given value.
      template <typename It>
      void expand(It first, It last) throw(BranchNodeException)
| Expand a leaf-node into a branch-node. The value of all children will be read from the first elements of the range first to last.
      bool operator==(const DTree &that) const
| Test if to DNodes are equal DNodes frmo the same tree - not if they actually contain the same data.
      bool operator!=(const DTree &that) const
| Negation of operator==.
      index_t index() const throw (NoParentException)
| Return the index of this node in its parent node.
      std::size_t depth() const
| Return the depth of the tree at this node.
      DNode parent() throw (NoParentException)
| Return the parent node. The root node has no parent and requesting it will throw an exception.
      const DNode parent() const throw (NoParentException)
| Return the parent node, read-only. The root node has no parent and requesting it will throw an exception.
      DTree<T, D> clone() const
| Return DTree containg a copy of part of the tree using the copy of this node as its root.
      std::size_t id() const
| Return a unique identifier associated with this node.
      std::vector<index_t> index_trail() const
| Return a `trail' of indices to take from the root node to the current node.
### Comparison To support interaction with datatypes that require comparison, such as std::map, a less-than-comparable operator is defined on DNodes in a DTree. It compares the nodes by their id(), which guaratees that the values are unique if the nodes are part of the same tree.
      template <typename T, std::size_t D>
      bool operator<(const DTree<T, D>::DNode &lhs, const DTree<T, D>::DNode &rhs);
| Returns true if the id() of lhs is smaller than that of rhs.
### I / O There are output operators for both entire DTrees and DNodes. An input operator only exists for entire DTrees, as an input operator for DNodes could lead to inconsistencies.
      template <typename T, std::size_t D>
      std::istream& operator>>(std::istream& i_stream,
    			 DTree<T, D> &tree)
    		throw(cvmlcpp::InvalidDTreeXML)
| Write a DTree to o_stream in formatted XML-like syntax.
      template <typename T, std::size_t D>
      std::ostream& operator<<(std::ostream& o_stream,
    		 const DNode<T, D> &node)
| Write a DNode, potentially with sub-nodes, to o_stream in formatted XML-like syntax.
      template <typename T, std::size_t D>
      std::istream& operator>>(std::istream& i_stream,
    			 DTree<T, D> &tree)
    	throw(cvmlcpp::InvalidDTreeXML)
| Read a DTree in XML format from i_stream.
## Examples For an example of a DTree holding items from a class-hierarchy, see Holder. ### A test-program
    #include <cvmlcpp/volume/DTree>

    int main()
    {
    	typedef cvmlcpp::DTree<int, 3> OctTreeInt;

    	// Initialize the tree with a value
    	OctTreeInt tree(7);
    	assert(tree.root()() == 7);

    	// The tree implicitly converts to its root node
    	assert(tree.root() == tree);

    	// Assign new value
    	tree() = 1; // implicitly assigned to the root node
    	tree.root()() = 5; // explicitly assigned to the root node
    	assert(tree.root()() == 5);

    	// Expanding a node without giving a value copies the current value
    	// to all new children.
    	tree.root().expand();
    	for (unsigned i = 0; i < OctTreeInt::N; ++i)
    		assert(tree[i]() == 5);

    	// Change one leaf node of the root and expand it to a branch node.
    	// The children of that node now all contain "3", the other children of
    	// the root node still have their original value
    	tree[0]() = 3;
    	tree[0].expand();
    	for (OctTreeInt::index_t i = 1; i < OctTreeInt::N; ++i)
    		assert(tree[i]() == 5);
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    		assert(tree[0][i]() == 3);

    	// Test if we can find a node by walking its trail of indices from
    	// the root node.
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    	{
    		const std::vector<OctTreeInt::index_t> trail = tree[0][i].index_trail();
    		OctTreeInt::DNode node = tree.root();
    		for (OctTreeInt::index_t j = 0; j < trail.size(); ++j)
    			node = node[ trail[j] ];
    		assert(node == tree[0][i]);
    	}

    	// Collapse the expanded node and assign it a value of 6
    	tree[0].collapse(6);
    	assert(tree[0]() == 6);

    	// Collapse the whole tree and assign it a value of 6
    	tree.collapse(4);
    	assert(tree.root()() == 4);

    	// Collapse nodes with grand-children
    	tree.expand();
    	tree[0].expand();
    	tree[0][0]() = 2;
    	tree.collapse(-2);
    	assert(tree.root()() == -2);
    	// Expand the tree, assign all children different values.
    	int values [] = {0, 1, 2, 3, 4, 5, 6, 7};
    	tree.expand(values, values+OctTreeInt::N);
    	assert(tree[3]() == 3);

    	// Grab a node in the tree
    	typedef OctTreeInt::DNode DNode8i;
    	DNode8i node = tree[3];

    	// See if all is consistent
    	assert(node != tree[2]);
    	assert(node == tree[3]);
    	assert(node.parent() == node.parent());
    	assert(node.parent() == tree.root());
    	assert(node != tree.root());

    	// Wrong things should throw
    	try { // Root node has no index!
    		assert(node.parent().index() >= 0);
    		assert(false); // previous should throw
    	}
    	catch(cvmlcpp::NoParentException &e) {
    	}

    	try { // Root node has no parent
    		DNode8i n = node.parent().parent();
    		assert(false); // previous should throw
    	}
    	catch(cvmlcpp::NoParentException &e) {
    	}

    	// Expand the node and fill with N different values
    	assert(node.isLeaf());
    	node.expand(values, values+OctTreeInt::N);
    	assert(!node.isLeaf());

    	// Verify that the i-th child of the node is the i-th child of the
    	// 3th child of the root.
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    	{
    		// This compares the nodes - NOT the values
    		assert(node[i] == tree[3][i]);

    		// Although the nodes are different ...
    		assert(node[i] != tree[i]);

    		// ... the values should be identical, except the expanded node.
    		if (i != 3)
    		{
    			// A value is obtained with operator()
    			assert(node[i]() == tree[i]());
    		}
    	}

    	// Copying data
    	OctTreeInt tree2 = tree.clone(); // Full tree copy
    	assert(tree2 != tree);

    	OctTreeInt tree3 = tree[3].clone(); // Partial tree copy;
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    	{
    		assert(tree [3][i]() == tree2[3][i]()); // all values equal
    		assert(tree3[i]() == tree2[3][i]()); // all values equal
    		assert(tree3[i].index() == tree2[3][i].index());
    		assert(tree3[i].index() == int(i));
    		assert(tree [3][i].depth() == 2u);
    		assert(tree2[3][i].depth() == 2u);
    		assert(tree3[i].depth() == 1u);
    	}

    	// Nodes can be identified with their ID. This ID indicates a
    	// position, it is valid in a copy of the tree.
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    	{
    		// Can we find ourselves ?
    		assert( tree[3][i] == tree.retrieve(tree[3][i].id()) );

    		// Equal in other tree (by value) ?
    		assert( tree[3][i]() == tree2.retrieve(tree[3][i].id())() );
    	}

    	// I/O
    	std::ofstream out("/tmp/tree.xml");
    	out << tree;
    	out.close();

    	OctTreeInt tree4;
    	std::ifstream in("/tmp/tree.xml");
    	in >> tree4;
    	in.close();
    	// Equal to other tree (by value) ?
    	for (OctTreeInt::index_t i = 0; i < OctTreeInt::N; ++i)
    	{
    		if (i != 3)
    			assert( tree[i]() == tree4.retrieve(tree[i].id())() );
    		assert( tree[3][i]() == tree4.retrieve(tree[3][i].id())() );
    	}

    	return 0;
    }
### A DTree in XML format. The XML fragment below encodes a DTree<int, 3>, i.e. an Octree filled with integers:
    <branch>
            <leaf>
                    <index> 0 </index>
                    <value> 0 </value>
            </leaf>
            <leaf>
                    <index> 1 </index>
                    <value> 1 </value>
            </leaf>
            <leaf>
                    <index> 2 </index>
                    <value> 2 </value>
            </leaf>
            <branch>
                    <index> 3 </index>
                    <leaf>
                            <index> 0 </index>
                            <value> 0 </value>
                    </leaf>
                    <leaf>
                            <index> 1 </index>
                            <value> 1 </value>
                    </leaf>
                    <leaf>
                            <index> 2 </index>
                            <value> 2 </value>
                    </leaf>
                    <leaf>
                            <index> 3 </index>
                            <value> 3 </value>
                    </leaf>
     		<leaf>
    			<index> 4 </index>
    			<value> 4 </value>
    		</leaf>
    		<leaf>
    			<index> 5 </index>
    			<value> 5 </value>
    		</leaf>
    		<leaf>
    			<index> 6 </index>
    			<value> 6 </value>
    		</leaf>
    		<leaf>
    			<index> 7 </index>
    			<value> 7 </value>
    		</leaf>
    	</branch>
    	<leaf>
    		<index> 4 </index>
    		<value> 4 </value>
    	</leaf>
    	<leaf>
    		<index> 5 </index>
    		<value> 5 </value>
    	</leaf>
    	<leaf>
    		<index> 6 </index>
    		<value> 6 </value>
    	</leaf>
    	<leaf>
    		<index> 7 </index>
    		<value> 7 </value>
    	</leaf>
    </branch>
Note that the format is not fully XML-compliant: the introductory "Doctype" header etc. is missing; spaces are required between tags and the values between them; a DTD is missing.