#!/usr/bin/python3 """ SPVO = Sparse Voxel Octree A Sparse Voxel Octree is a way of storing multidimensional data. (In this case it is 3D Data.) It works similarly to a Sparse Voxel Matrix, but it is a bit compressed. In a Sparse Voxel Octree, you have a root-node. The root node gets split up into 8 child nodes, which can be all split up into 8 more child nodes which can be split up too and so on. Thanks to this "compression", there are no zero values on places where there is just air unlike as in a normal matrix. """ class Node: def __init__(self): self.children = [None] * 8 self.leaf = True class SparseVoxelOctree: def __init__(self, data=None): self.root_node = Node() self.origin = (0, 0, 0) self.data = data def _get_child_index(self, x, y, z, size): index = 0 if x >= size // 2: index |= 1 x -= size // 2 if y >= size // 2: index |= 2 y -= size // 2 if z >= size // 2: index |= 4 z -= size // 2 return index, x, y, z def _extend_tree(self, x, y, z): new_root = Node() new_root.leaf = False index, nx, ny, nz = self._get_child_index(x, y, z, 2) new_root.children[index] = self.root_node self.root_node = new_root self.origin = ( self.origin[0] - (x >= 0) * 2 + 1, self.origin[1] - (y >= 0) * 2 + 1, self.origin[2] - (z >= 0) * 2 + 1 ) def _insert(self, node, x, y, z, size): while not size == 1: index, x, y, z = self._get_child_index(x, y, z, size) if node.children[index] is None: node.children[index] = Node() size //= 2 node.leaf = True def insert(self, x, y, z): # move origin if necessary while not (0 <= x < 2 ** 30 and 0 <= y < 2 ** 30 and 0 <= z < 2 ** 30): self._extend_tree(x, y, z) x, y, z = ( x - self.origin[0], y - self.origin[1], z - self.origin[2] ) self._insert(self.root_node, x, y, z, 2 ** 30)