CollisionAvoidance/src/spatial/QuadTree.h

142 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef AIRPORT_SPATIAL_QUADTREE_H
#define AIRPORT_SPATIAL_QUADTREE_H
#include <vector>
#include <memory>
#include "types/VehicleData.h"
// 定义矩形区域
struct Bounds {
double x; // 左上角x坐标
double y; // 左上角y坐标
double width; // 宽度
double height; // 高度
bool contains(const Vector2D& point) const {
return point.x >= x && point.x <= (x + width) &&
point.y >= y && point.y <= (y + height);
}
bool intersects(const Bounds& other) const {
return !(other.x > (x + width) ||
(other.x + other.width) < x ||
other.y > (y + height) ||
(other.y + other.height) < y);
}
};
template<typename T>
class QuadTree {
public:
explicit QuadTree(const Bounds& bounds, int capacity = 4)
: bounds_(bounds), capacity_(capacity) {}
void insert(const T& item) {
if (!bounds_.contains(getPosition(item))) {
return;
}
if (items_.size() < capacity_ && !divided_) {
items_.push_back(item);
return;
}
if (!divided_) {
subdivide();
}
northwest_->insert(item);
northeast_->insert(item);
southwest_->insert(item);
southeast_->insert(item);
}
std::vector<T> queryRange(const Bounds& range) const {
std::vector<T> found;
if (!bounds_.intersects(range)) {
return found;
}
for (const auto& item : items_) {
if (range.contains(getPosition(item))) {
found.push_back(item);
}
}
if (divided_) {
auto nw = northwest_->queryRange(range);
auto ne = northeast_->queryRange(range);
auto sw = southwest_->queryRange(range);
auto se = southeast_->queryRange(range);
found.insert(found.end(), nw.begin(), nw.end());
found.insert(found.end(), ne.begin(), ne.end());
found.insert(found.end(), sw.begin(), sw.end());
found.insert(found.end(), se.begin(), se.end());
}
return found;
}
std::vector<T> queryNearby(const Vector2D& point, double radius) const {
Bounds range{
point.x - radius,
point.y - radius,
radius * 2,
radius * 2
};
return queryRange(range);
}
void clear() {
items_.clear();
divided_ = false;
northwest_.reset();
northeast_.reset();
southwest_.reset();
southeast_.reset();
}
private:
Bounds bounds_;
int capacity_;
std::vector<T> items_;
bool divided_ = false;
std::unique_ptr<QuadTree> northwest_;
std::unique_ptr<QuadTree> northeast_;
std::unique_ptr<QuadTree> southwest_;
std::unique_ptr<QuadTree> southeast_;
void subdivide() {
double x = bounds_.x;
double y = bounds_.y;
double w = bounds_.width / 2;
double h = bounds_.height / 2;
Bounds nw{x, y, w, h};
northwest_ = std::make_unique<QuadTree>(nw, capacity_);
Bounds ne{x + w, y, w, h};
northeast_ = std::make_unique<QuadTree>(ne, capacity_);
Bounds sw{x, y + h, w, h};
southwest_ = std::make_unique<QuadTree>(sw, capacity_);
Bounds se{x + w, y + h, w, h};
southeast_ = std::make_unique<QuadTree>(se, capacity_);
divided_ = true;
}
// 获取对象的位置
static Vector2D getPosition(const T& item) {
if constexpr (std::is_same_v<T, VehicleData>) {
return item.position;
} else {
return item.getPosition(); // 对于其他类型假设有getPosition方法
}
}
};
#endif // AIRPORT_SPATIAL_QUADTREE_H