public void DrawQuadTreeGizmo() { for (int i = Nodes.Length - 1; i >= 0; i--) { LinkedQuadTreeNode node = Nodes[i]; Color color = Color.Lerp(Color.black, Color.white, 1f - ((float)node.Depth / (float)Height)); DrawNodeGizmo(node, color); } }
public void InsertValue(int value, LinkedQuadTreeNode node) { Assert.IsTrue(IsLeaf(node), "Value can be inserted only on leaf node!"); node.Value = value; foreach (LinkedQuadTreeNode n in GetAllParentNodes(node)) { n.Value += value; } }
public int[] GetCoordinateOfLeafNode(LinkedQuadTreeNode node) { int sides = NumberOfCellsPerSide(Nodes[0]); int indexOffset = GetNumberOfTreeNodes(Height - 1); int leafIndex = node.Index - indexOffset; int y = Mathf.FloorToInt(leafIndex / sides); int x = leafIndex % sides; return(new int[2] { x, y }); }
public void DrawNodeGizmo(LinkedQuadTreeNode node, Color color) { Vector2 position = node.Position; float size = node.Size; Vector2 a = position; Vector2 b = position + Vector2.right * size; Vector2 c = position + Vector2.up * size; Vector2 d = position + Vector2.one * size; Debug.DrawLine(a, b, color); Debug.DrawLine(b, d, color); Debug.DrawLine(d, c, color); Debug.DrawLine(c, a, color); }
public LinkedQuadTreeNode[] GetAllParentNodes(LinkedQuadTreeNode node, LinkedQuadTreeNode[] parentNodes = null) { if (parentNodes == null) { parentNodes = new LinkedQuadTreeNode[node.Depth]; } if (node.Depth > 0) { LinkedQuadTreeNode parentNode = GetParentNode(node); parentNodes[node.Depth - 1] = parentNode; return(GetAllParentNodes(parentNode, parentNodes)); } return(parentNodes); }
private bool TestGetCoordinateOfLeafNodeHeight3() { bool success = true; string messages = ""; int size = 128; int height = 3; LinkedQuadTree linkedQuadTree = new LinkedQuadTree(Vector2.zero, size, height); LinkedQuadTreeNode lastNode = linkedQuadTree.Nodes[linkedQuadTree.Nodes.Length - 1]; int[] coordinates = linkedQuadTree.GetCoordinateOfLeafNode(lastNode); TestAssert(coordinates[0] == 3, "Expected 3!", ref success, ref messages); TestAssert(coordinates[1] == 3, "Expected 3!", ref success, ref messages); return(success); }
private bool TestGetAllParentNodes() { bool success = true; string messages = ""; int size = 128; int height = 3; LinkedQuadTree linkedQuadTree = new LinkedQuadTree(new Vector2(-size / 2, -size / 2), size, height); LinkedQuadTreeNode lastNode = linkedQuadTree.Nodes[linkedQuadTree.Nodes.Length - 1]; LinkedQuadTreeNode[] parentNodes = linkedQuadTree.GetAllParentNodes(lastNode); TestAssert(parentNodes.Length == 2, "Expected 2 parent nodes!", ref success, ref messages); TestAssert(parentNodes[0].Index == 0, "Expected top parent to be root!", ref success, ref messages); TestAssert(parentNodes[1].Index == 4, "Expected second parent have index 4!", ref success, ref messages); return(success); }
private bool TestNumberOfCells() { bool success = true; string messages = ""; int size = 128; int height = 3; LinkedQuadTree linkedQuadTree = new LinkedQuadTree(new Vector2(-size / 2, -size / 2), size, height); LinkedQuadTreeNode lastNode = linkedQuadTree.Nodes[linkedQuadTree.Nodes.Length - 1]; TestAssert(linkedQuadTree.NumberOfCells(linkedQuadTree.Nodes[0]) == 16, "Expected 4 cells at this depth!", ref success, ref messages); TestAssert(linkedQuadTree.NumberOfCells(linkedQuadTree.Nodes[1]) == 4, "Expected 2 cells at this depth!", ref success, ref messages); TestAssert(linkedQuadTree.NumberOfCells(lastNode) == 1, "Expected 1 cell at this depth!", ref success, ref messages); TestAssert(linkedQuadTree.NumberOfCellsPerSide(linkedQuadTree.Nodes[0]) == 4, "Expected 4 cells at this depth!", ref success, ref messages); TestAssert(linkedQuadTree.NumberOfCellsPerSide(linkedQuadTree.Nodes[1]) == 2, "Expected 2 cells at this depth!", ref success, ref messages); TestAssert(linkedQuadTree.NumberOfCellsPerSide(lastNode) == 1, "Expected 1 cell at this depth!", ref success, ref messages); return(success); }
private void BuildQuadTreeRecursively(Vector2 position, float size, int height, int depth = 0, int index = 0, LinkedQuadTreeNode[] nodes = null) { nodes[index] = new LinkedQuadTreeNode(position, size, depth, index); if (depth + 1 >= height) { return; } float sizeHalf = size * 0.5f; Vector2 position1 = position; Vector2 position2 = position + Vector2.right * sizeHalf; Vector2 position3 = position + Vector2.up * sizeHalf; Vector2 position4 = position + Vector2.one * sizeHalf; int nextIndex = 4 * index; BuildQuadTreeRecursively(position1, sizeHalf, height, depth + 1, nextIndex + 1, nodes); BuildQuadTreeRecursively(position2, sizeHalf, height, depth + 1, nextIndex + 2, nodes); BuildQuadTreeRecursively(position3, sizeHalf, height, depth + 1, nextIndex + 3, nodes); BuildQuadTreeRecursively(position4, sizeHalf, height, depth + 1, nextIndex + 4, nodes); }
private bool TestEmptyAndFull() { int size = 128; int height = 2; LinkedQuadTree linkedQuadTree = new LinkedQuadTree(new Vector2(-size / 2, -size / 2), size, height); LinkedQuadTreeNode lastNode = linkedQuadTree.Nodes[linkedQuadTree.Nodes.Length - 1]; linkedQuadTree.InsertValue(1, lastNode); bool success = true; string messages = ""; TestAssert(linkedQuadTree.IsFull(linkedQuadTree.Nodes[4]) == true, "Expected cell 4 to be full!", ref success, ref messages); TestAssert(linkedQuadTree.IsFull(linkedQuadTree.Nodes[0]) == false, "Expected cell 0 not to be full!", ref success, ref messages); TestAssert(linkedQuadTree.IsEmpty(linkedQuadTree.Nodes[4]) == false, "Expected cell 4 not to be empty!", ref success, ref messages); TestAssert(linkedQuadTree.IsEmpty(linkedQuadTree.Nodes[0]) == false, "Expected cell 0 to be empty!", ref success, ref messages); TestAssert(linkedQuadTree.IsEmpty(linkedQuadTree.Nodes[1]) == true, "Expected cell 1 to be emtpy!", ref success, ref messages); return(success); }
public LinkedQuadTreeNode <T> Subdivide(Vector2 targetPosition, T newData, int depth = 0) { if (depth == 0) { return(this); } var subdivideIndex = GetIndexOfPosition(targetPosition, position); if (subNodes == null) { subNodes = new LinkedQuadTreeNode <T> [4]; for (int i = 0; i < subNodes.Length; i++) { Vector2 newPos = position; if ((i & 2) == 2) { newPos.y -= size * 0.25f; } else { newPos.y += size * 0.25f; } if ((i & 1) == 1) { newPos.x += size * 0.25f; } else { newPos.x -= size * 0.25f; } subNodes[i] = new LinkedQuadTreeNode <T>(newPos, size * 0.5f, depth - 1); } } return(subNodes[subdivideIndex].Subdivide(targetPosition, newData, depth - 1)); }
public float NormalizedValue(LinkedQuadTreeNode node) { return((float)node.Value / NumberOfCells(node)); }
public int NumberOfCellsPerSide(LinkedQuadTreeNode node) { return((int)Mathf.Pow(2, Height - 1 - node.Depth)); }
public bool IsEmpty(LinkedQuadTreeNode node) { return(node.Value == 0); }
public bool IsFull(LinkedQuadTreeNode node) { return(node.Value == NumberOfCells(node)); }
public bool IsLeaf(LinkedQuadTreeNode node) { return(node.Depth + 1 == Height); }
public LinkedQuadTreeNode GetParentNode(LinkedQuadTreeNode node) { int parentIndex = Mathf.FloorToInt((node.Index - 1) / 4); return(Nodes[parentIndex]); }
public void CircleSubdivide(LinkedList <LinkedQuadTreeNode <T> > selectectedNodes, Vector2 targetPosition, float radius, T newData, int depth = 0) { if (depth == 0) { Data = newData; selectectedNodes.AddLast(this); return; } var subdivideIndex = GetIndexOfPosition(targetPosition, position); if (IsLeaf()) { subNodes = new LinkedQuadTreeNode <T> [4]; for (int i = 0; i < subNodes.Length; i++) { Vector2 newPosition = position; if ((i & 2) == 2) { newPosition.y -= size * 0.25f; } else { newPosition.y += size * 0.25f; } if ((i & 1) == 1) { newPosition.x += size * 0.25f; } else { newPosition.x -= size * 0.25f; } subNodes[i] = new LinkedQuadTreeNode <T>(newPosition, size * 0.5f, depth - 1, Data); } } for (int i = 0; i < subNodes.Length; i++) { if (subNodes[i].ContainedInCircle(targetPosition, radius)) { subNodes[i].CircleSubdivide(selectectedNodes, targetPosition, radius, newData, depth - 1); } } bool shouldReduce = true; T initialData = subNodes[0].Data; for (int i = 0; i < subNodes.Length; i++) { shouldReduce &= initialData.CompareTo(subNodes[i].Data) == 0; shouldReduce &= subNodes[i].IsLeaf(); if (!shouldReduce) { break; } } if (shouldReduce) { Data = initialData; subNodes = null; } }
public LinkedQuadTree(Vector2 position, float size, int depth) { this.depth = depth; node = new LinkedQuadTreeNode <T>(position, size, depth); //node.Subdivide(depth); }