63 def octree_recursive_build(root, db, center, extent, point_indices, leaf_size, min_extent): 64 if len(point_indices) == 0: 65 return None 66 octree_recursive_build 67 if root is None: 68 root = Oct 68 root = Octant([None for i in range(8)], center, extent, point_indices, is_leaf=True) 69 70 # determine whether to split this octant 71 if len(point_indices) <= leaf_size or extent <= min_extent: 72 root.is_leaf = True 73 else:
point_indiand len(root.point_indices) > 0:ces: 确定现在这些点属于哪个小的Octant。我们可以先建立一个child_list=[[] for _ in range(8)],然后往这八个区域里面添加point的序号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
child_list=[[] for _ in range(8)] for point_idx in point_indices: point = db[point_idx] # 判断下标为point_idx的点应该要去哪个子区域 # 通过判断x, y, z和center的相对位置来判定去哪个子区域 zone = 0 if point[0] > center[0]: zone = zone | 1 if point[1] > center[1]: zone = zone | 2 if point[2] > center[2]: zone = zone | 4 # 把相应的点放入相应的区域 child_list[zone].append(point_idx)
def knn(root, query): if root.is_leaf(): pass else: zone = 0 if query[0] > root.center[0]: zone = zone | 1 if query[1] > root.center[1]: zone = zone | 2 if query[2] > root.center[2]: zone = zone | 4 knn(root.chilren[zone], query)
如果到了叶子节点,计算每一个点到query的距离
1 2 3 4 5 6 7 8
242 if root.is_leaf and len(root.point_indices) > 0: 243 # compare the contents of a leaf 244 leaf_points = db[root.point_indices, :] 245 diff = np.linalg.norm(np.expand_dims(query, 0) - leaf_points, axis=1) 246 for i in range(diff.shape[0]): 247 result_set.add_point(diff[i], root.point_indices[i]) 248 # check whether we can stop search now 249 return inside(query, result_set.worstDist(), root)
135 def overlaps(query: np.ndarray, radius: float, octant:Octant): 136 """ 137 Determines if the query ball overlaps with the octant 138 :param query: 139 :param radius: 140 :param octant: 141 :return: 142 """ 143 query_offset = query - octant.center 144 query_offset_abs = np.fabs(query_offset) 145 146 # completely outside, since query is outside the relevant area 147 max_dist = radius + octant.extent 148 if np.any(query_offset_abs > max_dist): 149 return False 150 151 # if pass the above check, consider the case that the ball is contacting the face of the octant 152 if np.sum((query_offset_abs < octant.extent).astype(np.int)) >= 2: 153 return True 154 155 # conside the case that the ball is contacting the edge or corner of the octant 156 # since the case of the ball center (query) inside octant has been considered, 157 # we only consider the ball center (query) outside octant 158 x_diff = max(query_offset_abs[0] - octant.extent, 0) 159 y_diff = max(query_offset_abs[1] - octant.extent, 0) 160 z_diff = max(query_offset_abs[2] - octant.extent, 0) 161 162 return x_diff * x_diff + y_diff * y_diff + z_diff * z_diff < radius * radius