1 #include <cmath>
2 #include <vector>
3 #include <iostream>
4 #include <algorithm>
5
6 using namespace std;
7
8 const int NUME_PLANETS = 10;//星球数量
9 const int TIME_COUNT = 20;
10 const int BORDER_LIMIT = 3200;//所有坐标绝对值都不超过3200
11
12 const double G = 1e-3;//万有引力常量
13 const double pi = acos(-1.0);//圆周率
14
15 double sqr(double x) {//平方
16 return x * x;
17 };
18
19 //二维向量
20 class Vector {
21 public:
22 double x, y;
23
24 Vector():x(0), y(0){}
25 Vector(double x, double y):x(x), y(y){}
26 ~Vector() {}
27
28 void operator = (const Vector &v) {
29 x = v.x;
30 y = v.y;
31 }
32
33 Vector operator + (const Vector &v) {
34 return Vector(x + v.x, y + v.y);
35 }
36
37 Vector operator - (const Vector &v) {
38 return Vector(x - v.x, y - v.y);
39 }
40
41 Vector operator * (double f) {
42 return Vector(x * f, y * f);
43 }
44
45 Vector operator / (double f) {
46 //return (*this) * (1.0 / f);
47 return Vector(x / f, y / f);
48 }
49
50 double length() {//返回长度的平方
51 return sqr(x) + sqr(y);
52 }
53
54 void factor() {//将该向量变为单位向量
55 double len = sqrt(length());
56 x /= len;
57 y /= len;
58 }
59
60 void print() {
61 cout << "(" << x << "," << y << ")";
62 }
63 };
64
65 //星球结构体
66 class Planet {
67 public:
68 Vector pos;//位置
69 Vector v;//速度
70 Vector a;//加速度
71 double m;//质量
72 };
73
74 //封装四叉树
75 namespace QuatTree {
76 const int SON = 4;//儿子个数,使用常量易于拓展,比如想拓展为八叉树只需要修改此常量为8即可
77 const int SIZE = 1e5 + 5;//预开SIZE个Node节点备用,应保证 SIZE >= NUME_PLANETS * log2(N), N表示初始边界大小
78
79 //四叉树的节点
80 struct Node {
81 double mass;//质量
82 Vector center;//重心
83 bool isleaf;//是否为叶子节点
84 Node* child[SON];
85 /*当前节点的四个儿子节点,分布如下
86 * 01
87 * 23
88 */
89
90 Node():mass(0), isleaf(0), center(){
91 for (int i = 0; i < SON; i ++)
92 child[i] = NULL;
93 }
94 ~Node() {}
95
96 void init(Planet *p);//使用一个星球对四叉树节点进行初始化
97 void update();//使用四个儿子节点的信息更新当前节点的信息
98 };
99
100 Node *null = new Node();//空指针,使用自定义null而不用NULL可以减少 if(Node == NULL) 的判断
101 Node *root;//四叉树的根
102
103 void Node::init(Planet *p) {
104 mass = p -> m;
105 isleaf = 1;
106 center = p -> pos;
107 child[0] = null;
108 child[1] = null;
109 child[2] = null;
110 child[3] = null;
111 }
112
113 void Node::update() {
114 mass = 0;
115 isleaf = 1;
116 center.x = center.y = 0;
117 for (int i = 0; i < SON; i ++) {
118 if (child[i] == null) continue;
119 isleaf = 0;
120 mass += child[i] -> mass;
121 center.x += child[i] -> mass * (child[i] -> center).x;
122 center.y += child[i] -> mass * (child[i] -> center).y;
123 }
124 center.x /= mass;
125 center.y /= mass;
126 }
127
128 Node pool[SIZE];//内存池
129 int count;//内存池的计数器
130
131 void init() {//四叉树初始化
132 count = 0;
133 root = null;
134 }
135
136 Node *getNewNode() {//从内存池中获得一个Node指针
137 return &(pool[count ++]);
138 }
139
140 void insert(Node *&o, Planet *p,
141 double lx = -BORDER_LIMIT, double rx = BORDER_LIMIT,
142 double ly = -BORDER_LIMIT, double ry = BORDER_LIMIT) {
143 //当前处理的二位平面为 lx <= x < rx, ly <= y < ry
144 if (o == null) {
145 o = getNewNode();
146 o -> init(p);
147 return;
148 }
149 double midx = (lx + rx) / 2, midy = (ly + ry) / 2;
150 if ((p -> pos).x < midx) {
151 if ((p -> pos).y < midy) insert(o -> child[0], p, lx, midx, ly, midy);
152 else insert(o -> child[2], p, lx, midx, midy, ry);
153 }
154 else {
155 if ((p -> pos).y < midy) insert(o -> child[1], p, lx, midx, ly, midy);
156 else insert(o -> child[3], p, lx, midx, midy, ry);
157 }
158 o -> update();
159 }
160
161 Planet calc(Planet *p, Node *o, int tim = 1000) {
162 //计算星球p,在已建好的四叉树o中,经过时间tim之后的状态
163
164 }
165
166 vector<Planet> getQuatTree(vector<Planet> planets, int tim = 1000) {
167 //星球集合planets经过时间tim后的状态,tim单位为ms,默认为1000ms
168 init();//初始化
169 int n = planets.size();//获得星球数量
170
171 for (int i = 0; i < n; i ++) {
172 insert(root, &planets[i]);
173 }
174
175 vector<Planet> result(n);
176 for (int i = 0; i < n; i ++) {
177 result[i] = calc(&planets[i], root, tim);
178 }
179
180 return result;
181 }
182 }
183
184 int main() {
185 vector<Planet> planets(NUME_PLANETS);
186 int num = NUME_PLANETS;
187
188 /*生成所有星球初始值
189 */
190
191 /*每隔一定时间进行一次计算即可,使用方法如下
192 * for (int i = 0; i < times; i ++) {//计算times次
193 * planets = QuatTree::getQuatTree(planets);
194 * print(planets);//输出所有星球信息
195 * }
196 */
197 return 0;
198 }