|         |      1 KdTree Algorithm | 
|         |      2 ---------------- | 
|         |      3  | 
|         |      4 def build_kdtree(root, shapes): | 
|         |      5 	root = new KdNode | 
|         |      6 	root.shapes = shapes | 
|         |      7 	subdivide(root, bounding_box(shapes), 0) | 
|         |      8  | 
|         |      9 def subdivide(node, bbox, depth): | 
|         |     10 	# choose split axis | 
|         |     11 	axis = bbox.largest_extend() | 
|         |     12  | 
|         |     13 	# find split position | 
|         |     14 	splitpos = find_split_position(axis) | 
|         |     15  | 
|         |     16 	leftnode, rightnode = new KdNode[2] | 
|         |     17 	for each shape: | 
|         |     18 		if (node->intersectleftnode()) leftnode->addprimitive( primitive ) | 
|         |     19 		if (node->intersectrightnode()) rightnode->addprimitive( primitive ) | 
|         |     20 	subdivide(leftnode, bbox.left_split(splitpos), depth+1) | 
|         |     21 	subdivide(rightnode, bbox.right_split(splitpos), depth+1) | 
|         |     22  | 
|         |     23 def find_split_position(axis): | 
|         |     24 	mshapes = new ShapeListWithMarks(shapes) | 
|         |     25  | 
|         |     26 	# sort new shape list according to left boundaries | 
|         |     27 	mshapes.sort(axis) | 
|         |     28  | 
|         |     29 	splitlist = new SplitList() | 
|         |     30 	for each mshape from mshapes: | 
|         |     31 		splitlist.add_extremes(mshape, axis) | 
|         |     32 	splitlist.sort() | 
|         |     33 	for each split from splitlist: | 
|         |     34 		for each mshape from mshapes: | 
|         |     35 			if mshape.marked: | 
|         |     36 				continue | 
|         |     37  | 
|         |     38 			# if shape is on left side of split plane | 
|         |     39 			if mshape.r_boundary <= split.pos: | 
|         |     40 				split.lnum++ | 
|         |     41 				mshape.mark() | 
|         |     42  | 
|         |     43 			# if shape is completely contained in split plane | 
|         |     44 			if mshape.l_boundary == mshape.r_boundary == split.pos: | 
|         |     45 				if split.num_smaller_subcell == 0: | 
|         |     46 					split.num_bigger_subcell++ | 
|         |     47 				else: | 
|         |     48 					split.num_smaller_subcell++ | 
|         |     49  | 
|         |     50 			# if shape is on right side of split plane | 
|         |     51 			if mshape.l_boundary >= split.pos: | 
|         |     52 				split.r_num += mshapes.count - mshape.number | 
|         |     53 				break | 
|         |     54  | 
|         |     55 			# if shape occupies both sides of split plane | 
|         |     56 			if mshape.l_boundary < split.pos and mshape.r_boundary > split.pos: | 
|         |     57 				split.l_num++ | 
|         |     58 				split.r_num++ |