17 for (
size_t i = 0; i < threads; ++i) {
18 workers.emplace_back([
this] {
20 std::function<void()> task;
22 std::unique_lock<std::mutex> lock(this->queue_mutex);
23 this->condition.wait(lock, [
this] {
return this->stop || !this->tasks.empty(); });
25 if (this->stop && this->tasks.empty())
return;
27 task = std::move(this->tasks.front());
38 std::unique_lock<std::mutex> lock(queue_mutex);
41 condition.notify_all();
42 for (std::thread& worker : workers) {
47template<
class F,
class... Args>
48auto ThreadPool::enqueue(F&& f, Args&&... args)
const -> std::future<
typename std::result_of<F(Args...)>::type> {
49 using return_type =
typename std::result_of<F(Args...)>::type;
51 auto task = std::make_shared<std::packaged_task<return_type()>>(
52 std::bind(std::forward<F>(f), std::forward<Args>(args)...)
55 std::future<return_type> res = task->get_future();
57 std::unique_lock<std::mutex> lock(queue_mutex);
60 throw std::runtime_error(
"enqueue on stopped ThreadPool");
63 tasks.emplace([task]() { (*task)(); });
65 condition.notify_one();
70 std::unique_lock<std::mutex> lock(queue_mutex);
71 condition.wait(lock, [
this] {
return tasks.empty(); });
77 if (root->is_full() && !root->is_leaf) {
79 auto new_root = std::make_unique<RTreeNode<T>>(
false);
80 new_root->children.push_back(std::move(root));
81 auto sibling = split_node(new_root->children[0].get());
82 new_root->children.push_back(std::move(sibling));
83 new_root->update_mbr();
84 root = std::move(new_root);
87 insert_recursive(root.get(),
object, bbox);
94 node->
entries.emplace_back(
object, bbox);
100 double min_increase = std::numeric_limits<double>::max();
101 size_t best_child = 0;
103 for (
size_t i = 0; i < node->
children.size(); ++i) {
104 double increase = calculate_area_increase(node->
children[i]->mbr, bbox);
105 if (increase < min_increase) {
106 min_increase = increase;
112 if (node->
children[best_child]->is_full()) {
113 auto sibling = split_node(node->
children[best_child].get());
114 node->
children.push_back(std::move(sibling));
117 min_increase = std::numeric_limits<double>::max();
120 for (
size_t i = 0; i < node->
children.size(); ++i) {
121 double increase = calculate_area_increase(node->
children[i]->mbr, bbox);
122 if (increase < min_increase) {
123 min_increase = increase;
129 insert_recursive(node->
children[best_child].get(),
object, bbox);
134std::unique_ptr<RTreeNode<T>> RTree<T>::split_node(
RTreeNode<T>* node) {
135 auto new_node = std::make_unique<RTreeNode<T>>(node->is_leaf);
139 size_t mid = node->entries.size() / 2;
140 new_node->entries.assign(node->entries.begin() + mid, node->entries.end());
141 node->entries.erase(node->entries.begin() + mid, node->entries.end());
144 size_t mid = node->children.size() / 2;
145 new_node->children.assign(
146 std::make_move_iterator(node->children.begin() + mid),
147 std::make_move_iterator(node->children.end())
149 node->children.erase(node->children.begin() + mid, node->children.end());
153 new_node->update_mbr();
160 std::vector<T> result;
161 query_recursive(root.get(), range, result);
172 for (
const auto& entry : node->
entries) {
173 if (entry.second.intersects(range)) {
174 result.push_back(entry.first);
178 for (
const auto& child : node->
children) {
179 query_recursive(child.get(), range, result);
192 double current_area = current.
area();
194 return union_area - current_area;
199 root = std::make_unique<RTreeNode<T>>(
true);
215 const std::string& parent_name) {
216 IPBlock* parent = find_block(parent_name);
218 throw std::runtime_error(
"Parent block not found: " + parent_name);
221 auto new_block = std::make_unique<IPBlock>(name, boundary, parent->
level + 1);
225 create_block_index(name, boundary);
229void HierarchicalSpatialIndex<T>::create_block_index(
const std::string& block_name,
234 if constexpr (std::is_same_v<T, geometry::Rectangle>) {
236 }
else if constexpr (std::is_same_v<T, geometry::Point>) {
239 return obj.bounding_box();
243 block_indices[block_name] = std::make_unique<QuadTree<T>>(boundary, bbox_func, 100, 8);
244 rtree_indices[block_name] = std::make_unique<RTree<T>>();
248IPBlock* HierarchicalSpatialIndex<T>::find_block(
const std::string& name)
const {
249 if (name ==
"root") {
250 return root_block.get();
256 if (block->name == target_name) {
259 for (
const auto& sub_block : block->sub_blocks) {
260 if (
auto found = search(sub_block.get(), target_name)) {
267 return search(root_block.get(), name);
271std::string HierarchicalSpatialIndex<T>::find_optimal_block(
const geometry::Rectangle& )
const {
281 std::vector<std::future<std::vector<std::pair<T, T>>>> futures;
284 for (
const auto& block_pair : block_indices) {
285 const auto& index = block_pair.second;
286 auto future = thread_pool.enqueue([&index]() {
287 return index->find_potential_intersections();
289 futures.push_back(std::move(future));
293 std::vector<std::pair<T, T>> result;
294 for (
auto& future : futures) {
295 auto block_intersections = future.get();
296 result.insert(result.end(), block_intersections.begin(), block_intersections.end());
303std::vector<std::future<std::vector<T>>> HierarchicalSpatialIndex<T>::dispatch_parallel_queries(
306 std::vector<std::future<std::vector<T>>> futures;
308 for (
const auto& block_pair : block_indices) {
309 const auto& block_name = block_pair.first;
310 const auto& index = block_pair.second;
312 IPBlock* block = find_block(block_name);
314 auto future = thread_pool.enqueue([&index, range]() {
315 return index->query_range(range);
317 futures.push_back(std::move(future));
329 std::function<void(
IPBlock*)> optimize_block = [&](
IPBlock* block) {
332 block->
level < max_hierarchy_levels) {
338 std::vector<geometry::Rectangle> quadrants = {
340 half_width, half_height),
342 half_width, half_height),
344 half_width, half_height),
346 half_width, half_height)
349 for (
size_t i = 0; i < 4; ++i) {
350 std::string sub_name = block->
name +
"_q" + std::to_string(i);
351 auto sub_block = std::make_unique<IPBlock>(sub_name, quadrants[i], block->
level + 1);
353 create_block_index(sub_name, quadrants[i]);
358 for (
const auto& sub_block : block->
sub_blocks) {
359 optimize_block(sub_block.get());
363 optimize_block(root_block.get());
371 std::function<void(
const IPBlock*)> count_block = [&](
const IPBlock* block) {
376 for (
const auto& sub_block : block->
sub_blocks) {
377 count_block(sub_block.get());
381 count_block(root_block.get());
395void HierarchicalSpatialIndex<T>::partition_objects_by_zorder(
const std::vector<std::pair<T, geometry::Rectangle>>& objects) {
397 for (
const auto& obj_pair : objects) {
399 zorder_buckets[z_order].push_back(obj_pair.first);
405 const std::vector<geometry::Rectangle>& query_patterns) {
410 std::unordered_map<std::string, int> block_access_count;
412 for (
const auto& query_rect : query_patterns) {
413 for (
const auto& block_pair : block_indices) {
414 const auto& block_name = block_pair.first;
415 IPBlock* block = find_block(block_name);
417 block_access_count[block_name]++;
Advanced spatial indexing for ultra-large scale EDA layouts.
2D point with high-precision coordinates and utility methods
Axis-aligned rectangle for bounding boxes and simple EDA components.
double area() const
Calculate rectangle area.
double y
Y coordinate of bottom-left corner.
double height
Height of rectangle.
Rectangle union_with(const Rectangle &other) const
Calculate union rectangle that contains both rectangles.
bool intersects(const Rectangle &other) const
Check if this rectangle intersects with another rectangle.
double x
X coordinate of bottom-left corner.
double width
Width of rectangle.
Hierarchical spatial index for ultra-large datasets.
void create_ip_block(const std::string &name, const geometry::Rectangle &boundary, const std::string &parent_name="root")
void optimize_for_query_pattern(const std::vector< geometry::Rectangle > &query_patterns)
std::vector< std::pair< T, T > > parallel_find_intersections() const
Statistics get_statistics() const
void optimize_hierarchy()
High-performance R-tree implementation.
void insert(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_point(const geometry::Point &point) const
bool remove(const T &object, const geometry::Rectangle &bbox)
std::vector< T > query_range(const geometry::Rectangle &range) const
auto enqueue(F &&f, Args &&... args) const -> std::future< typename std::result_of< F(Args...)>::type >
ThreadPool(size_t threads=std::thread::hardware_concurrency())
void wait_for_completion()
static uint64_t encode_point(const geometry::Point &point, const geometry::Rectangle &bounds)
Main namespace for ZLayout library.
size_t avg_objects_per_block
IP Block represents a hierarchical design block.
geometry::Rectangle boundary
std::vector< size_t > component_ids
bool intersects(const geometry::Rectangle &rect) const
void add_sub_block(std::unique_ptr< IPBlock > block)
std::vector< std::unique_ptr< IPBlock > > sub_blocks
R-tree node for efficient rectangle indexing.
std::vector< std::pair< T, geometry::Rectangle > > entries
std::vector< std::unique_ptr< RTreeNode< T > > > children