Created
January 26, 2025 02:31
-
-
Save GeorgiyRyaposov/880f3933971d5ad76ea9f5886a7be0d5 to your computer and use it in GitHub Desktop.
Generic 2d quad tree implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
namespace Code.Scripts.Utils | |
{ | |
public class QuadTree<T> where T : Component | |
{ | |
private const int Capacity = 4; | |
private readonly Rect _bounds; | |
private readonly List<T> _items; | |
private QuadTree<T>[] _children; | |
public QuadTree(Rect bounds) | |
{ | |
_bounds = bounds; | |
_items = new List<T>(); | |
_children = null; | |
} | |
public void Insert(T item) | |
{ | |
if (!_bounds.Contains(item.transform.position)) | |
{ | |
return; | |
} | |
if (_items.Count < Capacity) | |
{ | |
_items.Add(item); | |
} | |
else | |
{ | |
if (_children == null) | |
{ | |
Subdivide(); | |
} | |
foreach (var child in _children) | |
{ | |
child.Insert(item); | |
} | |
} | |
} | |
public bool Remove(T item) | |
{ | |
if (!_bounds.Contains(item.transform.position)) | |
{ | |
return false; | |
} | |
// Если объект находится в текущем узле, удаляем его | |
if (_items.Remove(item)) | |
{ | |
return true; | |
} | |
// Если узел имеет дочерние узлы, рекурсивно удаляем объект из них | |
if (_children != null) | |
{ | |
foreach (var child in _children) | |
{ | |
if (child.Remove(item)) | |
{ | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
// Разделение узла на 4 дочерних узла | |
private void Subdivide() | |
{ | |
var halfWidth = _bounds.width / 2; | |
var halfHeight = _bounds.height / 2; | |
_children = new QuadTree<T>[4]; | |
_children[0] = new QuadTree<T>(new Rect(_bounds.x, _bounds.y, halfWidth, halfHeight)); | |
_children[1] = new QuadTree<T>(new Rect(_bounds.x + halfWidth, _bounds.y, halfWidth, halfHeight)); | |
_children[2] = new QuadTree<T>(new Rect(_bounds.x, _bounds.y + halfHeight, halfWidth, halfHeight)); | |
_children[3] = new QuadTree<T>(new Rect(_bounds.x + halfWidth, _bounds.y + halfHeight, halfWidth, halfHeight)); | |
// Перераспределяем объекты в дочерние узлы | |
foreach (var obj in _items) | |
{ | |
foreach (var child in _children) | |
{ | |
child.Insert(obj); | |
} | |
} | |
_items.Clear(); | |
} | |
// Поиск объектов в заданной области | |
public void Query(Rect area, List<T> found) | |
{ | |
if (!_bounds.Overlaps(area)) | |
{ | |
return; | |
} | |
foreach (var obj in _items) | |
{ | |
if (area.Contains(obj.transform.position)) | |
{ | |
found.Add(obj); | |
} | |
} | |
if (_children != null) | |
{ | |
foreach (var child in _children) | |
{ | |
child.Query(area, found); | |
} | |
} | |
} | |
public void Clear() | |
{ | |
_items.Clear(); | |
if (_children != null) | |
{ | |
foreach (var child in _children) | |
{ | |
child.Clear(); | |
} | |
} | |
_children = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment