108 bool intersects_boundary(
const T&
object,
const BoundingBoxFunc& get_bbox)
const;
126 std::unique_ptr<QuadTreeNode<T>> root;
131 bool collect_statistics;
132 mutable std::mutex tree_mutex;
144 size_t capacity = 10,
145 size_t max_depth = 8);
188 std::function<
bool(
const T&,
const T&)> collision_func)
const;
193 size_t size()
const {
return object_count; }
198 bool empty()
const {
return object_count == 0; }
230 void rebuild(
size_t new_capacity,
size_t new_max_depth);
245 bool update(
const T& old_object,
const T& new_object);
267 std::vector<T> objects;
268 size_t current_index;
360 const std::vector<geometry::Rectangle>& regions)
const;
394 void collect_all_objects(
const QuadTreeNode<T>* node, std::vector<T>& objects)
const;
399 void find_k_nearest_recursive(
const QuadTreeNode<T>* node,
const T& target,
400 size_t k, std::vector<std::pair<T, double>>& candidates)
const;
405 void calculate_detailed_statistics_recursive(
const QuadTreeNode<T>* node,
406 DetailedStatistics& stats)
const;
417 const std::string& indent =
"")
const;
437 size_t capacity = 10,
438 size_t max_depth = 8);
445 size_t capacity = 10,
446 size_t max_depth = 8);
463 if (!intersects_boundary(
object, get_bbox)) {
480 for (
int i = 0; i < 4; ++i) {
498 std::vector<T> result;
506 for (
const auto&
object :
objects) {
509 result.push_back(
object);
515 for (
int i = 0; i < 4; ++i) {
516 auto child_results =
children[i]->query_range(range, get_bbox);
517 result.insert(result.end(), child_results.begin(), child_results.end());
527 std::vector<T> result;
530 if (!
boundary.contains_point(point)) {
535 for (
const auto&
object :
objects) {
538 result.push_back(
object);
544 for (
int i = 0; i < 4; ++i) {
545 auto child_results =
children[i]->query_point(point, get_bbox);
546 result.insert(result.end(), child_results.begin(), child_results.end());
554void QuadTreeNode<T>::subdivide() {
555 double x = boundary.x;
556 double y = boundary.y;
557 double w = boundary.width / 2.0;
558 double h = boundary.height / 2.0;
561 children[0] = std::make_unique<QuadTreeNode>(
563 children[1] = std::make_unique<QuadTreeNode>(
565 children[2] = std::make_unique<QuadTreeNode>(
567 children[3] = std::make_unique<QuadTreeNode>(
574bool QuadTreeNode<T>::intersects_boundary(
const T&
object,
const BoundingBoxFunc& get_bbox)
const {
575 return boundary.intersects(get_bbox(
object));
582 for (
int i = 0; i < 4; ++i) {
593 for (
int i = 0; i < 4; ++i) {
602 std::vector<T> result =
objects;
604 for (
int i = 0; i < 4; ++i) {
605 auto child_objects =
children[i]->get_all_objects();
606 result.insert(result.end(), child_objects.begin(), child_objects.end());
617 : root(std::make_unique<
QuadTreeNode<T>>(boundary, capacity, max_depth, 0)),
618 get_bounding_box(get_bbox),
621 max_depth(max_depth),
622 collect_statistics(true) {
628 std::lock_guard<std::mutex> lock(tree_mutex);
630 if (root->insert(
object, get_bounding_box)) {
639 std::lock_guard<std::mutex> lock(tree_mutex);
641 return root->query_range(range, get_bounding_box);
646 std::lock_guard<std::mutex> lock(tree_mutex);
648 return root->query_point(point, get_bounding_box);
655 return std::vector<T>();
662 return std::vector<std::pair<T, T>>();
667 std::function<
bool(
const T&,
const T&)> collision_func)
const {
670 return std::vector<std::pair<T, T>>();
675 std::lock_guard<std::mutex> lock(tree_mutex);
683 std::lock_guard<std::mutex> lock(tree_mutex);
701 std::lock_guard<std::mutex> lock(tree_mutex);
703 if (remove_from_node(root.get(),
object)) {
711bool QuadTree<T>::remove_from_node(
QuadTreeNode<T>* node,
const T&
object) {
712 if (!node)
return false;
715 auto it = std::find(node->
objects.begin(), node->
objects.end(),
object);
716 if (it != node->
objects.end()) {
723 for (
int i = 0; i < 4; ++i) {
724 if (remove_from_node(node->
children[i].get(),
object)) {
735 std::lock_guard<std::mutex> lock(tree_mutex);
738 return insert(new_object);
745 std::lock_guard<std::mutex> lock(tree_mutex);
747 size_t success_count = 0;
748 for (
const auto&
object : objects) {
749 if (root->insert(
object, get_bounding_box)) {
754 return success_count;
759 std::lock_guard<std::mutex> lock(tree_mutex);
761 size_t success_count = 0;
762 for (
const auto&
object : objects) {
763 if (remove_from_node(root.get(),
object)) {
768 return success_count;
785 return std::find(candidates.begin(), candidates.end(),
object) != candidates.end();
790 std::lock_guard<std::mutex> lock(tree_mutex);
792 std::vector<T> result;
793 collect_all_objects(root.get(), result);
798void QuadTree<T>::collect_all_objects(
const QuadTreeNode<T>* node, std::vector<T>& objects)
const {
801 objects.insert(objects.end(), node->
objects.begin(), node->
objects.end());
804 for (
int i = 0; i < 4; ++i) {
805 collect_all_objects(node->
children[i].get(), objects);
814 2 * radius, 2 * radius);
817 std::vector<T> result;
818 for (
const auto& candidate : candidates) {
822 if (center.
distance_to(candidate_center) <= radius) {
823 result.push_back(candidate);
832 std::vector<std::pair<T, double>> candidates;
833 find_k_nearest_recursive(root.get(), target, k, candidates);
836 std::sort(candidates.begin(), candidates.end(),
837 [](
const auto& a,
const auto& b) { return a.second < b.second; });
839 std::vector<T> result;
840 for (
size_t i = 0; i < std::min(k, candidates.size()); ++i) {
841 result.push_back(candidates[i].first);
848void QuadTree<T>::find_k_nearest_recursive(
const QuadTreeNode<T>* node,
const T& target,
849 size_t k, std::vector<std::pair<T, double>>& candidates)
const {
855 for (
const auto&
object : node->
objects) {
856 if (
object == target)
continue;
859 double distance = target_bbox.
distance_to(obj_bbox);
860 candidates.emplace_back(
object, distance);
865 for (
int i = 0; i < 4; ++i) {
866 find_k_nearest_recursive(node->
children[i].get(), target, k, candidates);
876 size_t optimal_capacity = std::max(1UL, object_count / stats.total_nodes);
877 size_t optimal_depth = std::max(1UL, stats.max_depth_reached);
880 rebuild(optimal_capacity, optimal_depth);
888 calculate_detailed_statistics_recursive(root.get(), stats);
905void QuadTree<T>::calculate_detailed_statistics_recursive(
const QuadTreeNode<T>* node,
906 DetailedStatistics& stats)
const {
910 stats.total_objects += node->
objects.size();
911 stats.max_depth_reached = std::max(stats.max_depth_reached, node->
depth);
913 if (node->
depth < stats.objects_per_level.size()) {
914 stats.objects_per_level[node->
depth] += node->
objects.size();
919 if (stats.min_depth_reached == 0 || node->
depth < stats.min_depth_reached) {
920 stats.min_depth_reached = node->
depth;
923 stats.internal_nodes++;
924 for (
int i = 0; i < 4; ++i) {
925 calculate_detailed_statistics_recursive(node->
children[i].get(), stats);
932 return validate_node(root.get());
937 if (!node)
return true;
940 for (
const auto&
object : node->
objects) {
949 for (
int i = 0; i < 4; ++i) {
950 if (!validate_node(node->
children[i].get())) {
961 std::string result =
"QuadTree Structure:\n";
962 node_to_string(root.get(), result);
967void QuadTree<T>::node_to_string(
const QuadTreeNode<T>* node, std::string& result,
968 const std::string& indent)
const {
971 result += indent +
"Node: " + std::to_string(node->
objects.size()) +
" objects\n";
974 for (
int i = 0; i < 4; ++i) {
975 result += indent +
" Child " + std::to_string(i) +
":\n";
976 node_to_string(node->
children[i].get(), result, indent +
" ");
983 if (object_count == 0)
return 0.0;
986 size_t total_capacity = stats.total_nodes * capacity;
987 return static_cast<double>(object_count) / total_capacity;
2D point with high-precision coordinates and utility methods
double distance_to(const Point &other) const
Calculate Euclidean distance to another point.
Axis-aligned rectangle for bounding boxes and simple EDA components.
Point center() const
Get center point of rectangle.
bool intersects(const Rectangle &other) const
Check if this rectangle intersects with another rectangle.
bool contains_point(const Point &point) const
Check if point is inside rectangle (inclusive of boundary)
double distance_to(const Rectangle &other) const
Calculate minimum distance to another rectangle.
Iterator support for tree traversal.
const T * operator->() const
Iterator(const QuadTree *tree, bool is_end=false)
bool operator!=(const Iterator &other) const
bool operator==(const Iterator &other) const
const T & operator*() const
Quadtree spatial index for efficient range and intersection queries.
bool insert(const T &object)
Insert object into quadtree.
const QuadTreeNode< T > * get_root() const
Get root node (for visualization/debugging)
void clear()
Clear all objects from tree.
std::vector< T > get_all_objects() const
Get all objects in tree as vector.
bool empty() const
Check if tree is empty.
std::string to_string() const
Get tree as string representation (for debugging)
bool contains(const T &object) const
Check if object exists in tree.
size_t batch_remove(const std::vector< T > &objects)
Batch remove multiple objects efficiently.
std::function< geometry::Rectangle(const T &)> BoundingBoxFunc
size_t size() const
Get total number of objects in tree.
std::vector< T > query_range(const geometry::Rectangle &range) const
Query objects in rectangular range.
std::vector< T > query_k_nearest(const T &target, size_t k) const
Get k nearest neighbors to target object.
QuadTree(const geometry::Rectangle &boundary, BoundingBoxFunc get_bbox, size_t capacity=10, size_t max_depth=8)
Constructor.
Statistics get_statistics() const
Calculate tree statistics.
bool update(const T &old_object, const T &new_object)
Update object position (remove and re-insert)
void optimize()
Optimize tree structure for better performance This rebuilds the tree with better parameters based on...
DetailedStatistics get_detailed_statistics() const
Get detailed statistics about tree structure.
std::vector< std::pair< T, T > > find_intersections(std::function< bool(const T &, const T &)> collision_func) const
Find intersecting objects using efficient spatial queries.
void rebuild(size_t new_capacity, size_t new_max_depth)
Rebuild tree with new parameters.
Iterator end() const
Get iterator to end of tree.
void set_statistics_collection(bool enable)
Enable/disable statistics collection.
bool merge(const QuadTree &other)
Merge another quadtree into this one.
bool remove(const T &object)
Remove object from tree.
std::vector< std::unique_ptr< QuadTree > > split_by_regions(const std::vector< geometry::Rectangle > ®ions) const
Split tree into multiple subtrees based on spatial regions.
double get_load_factor() const
Get current load factor of the tree.
std::vector< T > query_circle(const geometry::Point ¢er, double radius) const
Get objects within circular range.
std::vector< T > query_point(const geometry::Point &point) const
Query objects containing a specific point.
bool validate() const
Validate tree structure integrity.
size_t batch_insert(const std::vector< T > &objects)
Batch insert multiple objects efficiently.
std::vector< std::pair< T, T > > find_potential_intersections() const
Find all potentially intersecting pairs of objects.
Iterator begin() const
Get iterator to beginning of tree.
std::vector< T > query_nearby(const T &target, double distance) const
Find objects within distance of target object.
A node in the quadtree structure.
std::vector< T > objects
Objects stored in this node.
std::function< geometry::Rectangle(const T &)> BoundingBoxFunc
size_t depth
Current depth in tree.
bool is_divided() const
Check if this node has been subdivided.
std::unique_ptr< QuadTreeNode > children[4]
Child nodes (NW, NE, SW, SE)
std::vector< T > query_range(const geometry::Rectangle &range, const BoundingBoxFunc &get_bbox) const
Query objects in a rectangular range.
void clear()
Clear all objects and children.
size_t size() const
Get total number of objects in this subtree.
bool divided
Whether this node has been subdivided.
size_t max_depth
Maximum subdivision depth.
std::vector< T > query_point(const geometry::Point &point, const BoundingBoxFunc &get_bbox) const
Query objects containing a specific point.
QuadTreeNode(const geometry::Rectangle &boundary, size_t capacity=10, size_t max_depth=8, size_t depth=0)
Constructor.
geometry::Rectangle boundary
Spatial boundary of this node.
std::vector< T > get_all_objects() const
Get all objects in this subtree.
size_t capacity
Maximum objects before subdivision.
bool insert(const T &object, const BoundingBoxFunc &get_bbox)
Insert object into this node or appropriate child.
QuadTree< geometry::Point > PointQuadTree
QuadTree specialized for Point objects (using Point as both object and bounding box)
QuadTree< geometry::Rectangle > RectangleQuadTree
QuadTree specialized for Rectangle objects.
std::unique_ptr< RectangleQuadTree > create_rectangle_quadtree(const geometry::Rectangle &boundary, size_t capacity=10, size_t max_depth=8)
Create QuadTree for rectangles with default bounding box function.
std::unique_ptr< PointQuadTree > create_point_quadtree(const geometry::Rectangle &boundary, size_t capacity=10, size_t max_depth=8)
Create QuadTree for points with default bounding box function.
Main namespace for ZLayout library.
2D Point class for geometric calculations
Axis-aligned rectangle class for bounding boxes and simple components.
Get detailed tree statistics.
double average_objects_per_leaf
std::vector< size_t > objects_per_level
double memory_usage_bytes
Get tree statistics for performance analysis.
double average_objects_per_leaf