-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathQTree.h
154 lines (128 loc) · 3.43 KB
/
QTree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#ifndef __QTREE__
#define __QTREE__
/*************************************
简易四叉树
除叶子节点外,每个节点都有四个孩子。
只有叶子节点能包含实体节点(坐标)。
不存在这样的中间节点,其四个孩子都是没有保存实体的叶子节点。
此处的实体节点是ecs中真正实体的坐标信息。
实现基本操作插入和删除。
entity移动时候利用这两个基本操作实现位置在树中的更新。
**************************************/
#include "PreHeader.h"
#include "Geometry.h"
struct QTreePos : public Position
{
Rect preArea;
void *entity;
QTreePos(float _x = 0.0f, float _y = 0.0f, void *e = nullptr):Position(_x, _y),
entity(e)
{
}
QTreePos(Position pos, void *e = nullptr):Position(pos),
entity(e)
{
}
bool operator == (const QTreePos &pos) const
{
return x == pos.x && y == pos.y;
}
bool IsInPreArea()
{
return preArea.is_contain(*this);
}
void Update(Position pos)
{
x = pos.x;
y = pos.y;
}
};
class QTree //四叉树类
{
private:
enum Direct
{
lu = 0,
ru = 1,
rd = 2,
ld = 3
};
struct Node
{
typedef std::vector<QTreePos*> Entities;
typedef std::size_t Count;
Count count;
Rect area;
Entities entitys; //实体的坐标,会随着实体移动,所以只是持有一个坐标的指针,不拷贝,不析构
Node * sub_area[4];
Node * parent; //指向父亲的指针,调节的时候会用到
Node(const Rect &, Node *, Count c = 4);
~Node();
//辅助函数,显示标记为内联函数
bool is_leaf() const
{
return sub_area[lu] == nullptr &&
sub_area[ru] == nullptr &&
sub_area[rd] == nullptr &&
sub_area[ld] == nullptr;
}
bool is_full() const
{
return count < entitys.size();
}
bool is_empty() const
{
return entitys.size() == 0;
}
Entities::iterator find_entity(const QTreePos &pos)
{
for(auto it = entitys.begin(); it != entitys.end(); ++it)
{
if(pos == **it)
{
return it;
}
}
return entitys.end();
}
void erase_entity(const Entities::iterator &it)
{
entitys.erase(it);
delete *it;
}
};
Node *root;
public:
QTree(const Rect &);
~QTree();
//更新所有节点的坐标,可能会包含插入删除操作,一帧一次
void Update();
//插入一个节点
void insert(QTreePos *);
//删除一个节点
void remove(QTreePos *);
//返回找到的节点序列
std::vector<QTreePos> findInRect(const Rect &rt);
private:
void Update(Node *);
void insert(QTreePos *, Node &);
void remove(QTreePos *, Node &);
void find_in_node(const Node &, const Rect &, std::vector<QTreePos> &);
void adjust(Node &); //删除操作可能出现四个叶子都没有保存实体,用此函数调整
Rect cut_rect(const Rect &rec, const Direct dir)
{
QTreePos center((rec.lu.x + rec.rd.x)/2, (rec.lu.y + rec.rd.y)/2);
switch (dir)
{
case lu:
return Rect(rec.lu, center);
case ru:
return Rect(QTreePos(center.x, rec.lu.y), QTreePos(rec.rd.x, center.y));
case rd:
return Rect(center, rec.rd);
case ld:
return Rect(QTreePos(rec.lu.x, center.y), QTreePos(center.x, rec.rd.y));
}
}
};
#endif