1 module Engine.Tree.BBTree;
2 
3 import Engine.math;
4 alias ulong TimeStamp;
5 alias ulong Hash;
6 import std.stdio;
7 import Engine.Allocator;
8 import std.parallelism;
9 import std.concurrency;
10 import core.atomic;
11 
12 alias ulong delegate(Indexable a,Indexable b, ulong collisionID) SpatialIndexQueryFunc;
13 alias void delegate(Node* node)  HashSetIterator;
14 
15 shared class Stack(T) {
16 	private shared struct Node {
17 		T _payload;
18 		Node * _next;
19 	}
20 	private Node * _root;
21 	
22 	void push(T value) {
23 		auto n = cast(shared)new Node(value);
24 		n._payload = value;
25 		shared(Node)* oldRoot;
26 		do {
27 			oldRoot = _root;
28 			n._next = oldRoot;
29 		} while (!cas(&_root, oldRoot, n));
30 	}
31 	
32 	shared(T)* pop() {
33 		typeof(return) result;
34 		shared(Node)* oldRoot;
35 		do {
36 			oldRoot = _root;
37 			if (!oldRoot) return null;
38 			result = & oldRoot._payload;
39 		} while (!cas(&_root, oldRoot, oldRoot._next));
40 		return result;
41 	}
42 
43 	bool empty() {
44 		if (atomicLoad(_root))
45 			return false;
46 		return true;
47 	}
48 }
49 
50 class BBTree : Tree
51 {
52 	ChunkAllocator!(Node, 100) nodeAllocator;
53 	int allocatedNodes = 0;
54 	int freedNodes = 0;
55 
56 	Node*[Indexable] leaves;
57 	Node* root;
58 
59 	@property ref TimeStamp stamp() {
60 		return stamp_;
61 	}
62 	TimeStamp stamp_;
63 
64 	Tree staticTree;
65 	Tree dynamicTree;
66 
67 	this(Tree staticTree)
68 	{
69 		if (staticTree !is null) {
70 			this.staticTree = staticTree;
71 		}
72 		stamp_ = 0;
73 	}
74 
75 	@property size_t length() const {
76 		return leaves.length;
77 	}
78 
79 	void Each(HashSetIterator func) {
80 		foreach (Node* node; leaves) {
81 			func(node);
82 		}
83 	}
84 
85 	void Insert(Indexable obj ) {
86 		auto leaf = NewLeaf(obj);
87 		leaves[obj] = leaf;	
88 		this.root = this.SubtreeInsert(this.root, leaf);
89 		leaf.stamp = GetMasterTree().stamp;
90 		IncrementStamp();
91 	}
92 
93 
94 	void Query(Indexable obj, rect bb, SpatialIndexQueryFunc func) {
95 		if(root) 
96 			SubtreeQuery(root, obj, bb, func);
97 	}
98 
99 	void SubtreeQuery(Node *subtree, Indexable obj, rect bb, SpatialIndexQueryFunc func)
100 	{
101         if(rect.Intersects(subtree.bb, bb)){
102 			if(subtree.NodeIsLeaf()){
103 				func(obj, subtree.obj, 0);
104 			} else {
105 				SubtreeQuery(subtree.a, obj, bb, func);
106 				SubtreeQuery(subtree.b, obj, bb, func);
107 			}
108         }
109 	}
110 
111 	void LeafQuery()(Node *subtree, Node *leaf, SpatialIndexQueryFunc func)
112 	{
113         if(rect.Intersects(leaf.bb, subtree.bb)){
114 			if(subtree.NodeIsLeaf()) {
115 				if (func !is null) {
116 					func(leaf.obj, subtree.obj, 0);
117 				}
118 			} else {
119 				LeafQuery(subtree.a, leaf,func);
120 				LeafQuery(subtree.b, leaf,func);
121 			}
122         }
123 	}
124 
125 	void NodeQuery()(Node *leaf, Node *staticRoot, SpatialIndexQueryFunc func)
126 	{
127 		if(staticRoot !is null) 
128 			LeafQuery(staticRoot, leaf, func);
129 
130 		for(Node *node = leaf; node.parent !is null; node = node.parent){
131 			if(node == node.parent.a){
132 				LeafQuery(node.parent.b, leaf, func);
133 			}
134 		}
135 	}
136 
137 
138 	void SubtreeSelfQuery()(Node *subtree, Node *staticRoot, SpatialIndexQueryFunc func) {
139 		if(subtree.NodeIsLeaf()){
140 			NodeQuery(subtree,staticRoot,func);
141         } else {
142 			SubtreeSelfQuery(subtree.a,staticRoot,func);
143 			SubtreeSelfQuery(subtree.b,staticRoot,func); // TODO: Force TCO here?
144         }
145 	}
146 
147 	bool LeafUpdate(Node *leaf)
148 	{
149 		auto rt = root;
150         if(!rect.Contains(leaf.bb, leaf.obj.BB())){
151 			leaf.bb = BB(leaf.obj);
152 
153 			rt = SubtreeRemove(rt, leaf);
154 			root = SubtreeInsert(rt, leaf);
155 
156 			leaf.stamp = GetMasterTree.stamp;
157 
158 			return true;
159         } else {
160 			return false;
161         }
162 	}
163 
164 	Node* NodeFromPool() {
165 		allocatedNodes++;
166 		return nodeAllocator.allocate();
167 	}
168 
169 	void NodeRecycle(Node *node)
170 	{
171 		freedNodes++;
172 		node.parent = null;
173 		nodeAllocator.free(node);
174 	}
175 
176 	Node* SubtreeRemove(Node *subtree, Node *leaf)
177 	{
178         if(leaf == subtree){
179 			return null;
180         } else {
181 			Node *parent = leaf.parent;
182 			if(parent == subtree){
183 				Node *other = subtree.NodeOther(leaf);
184 				other.parent = subtree.parent;
185 				NodeRecycle(subtree);
186 				return other;
187 			} else {
188 				NodeReplaceChild(parent.parent, parent, parent.NodeOther(leaf));
189 				return subtree;
190 			}
191         }
192 	}
193 
194 	void NodeReplaceChild(Node *parent, Node *child, Node *value)
195 	{
196 		assert(!parent.NodeIsLeaf(), "Internal Error: Cannot replace child of a leaf.");
197         assert(child == parent.a || child == parent.b, "Internal Error: Node is not a child of parent.");
198 
199         if(parent.a == child){
200 			NodeRecycle(parent.a);
201 			parent.NodeSetA(value);
202         } else {
203 			NodeRecycle(parent.b);
204 			parent.NodeSetB(value);
205         }
206 
207         for(Node *node=parent; node; node = node.parent){
208 			node.bb = rect.Merge(node.a.bb, node.b.bb);
209         }
210 	}
211 
212 	void ReindexQuery(SpatialIndexQueryFunc func)
213 	{
214         if(root is null) return;
215 
216         // LeafUpdate() may modify tree->root. Don't cache it.
217 		foreach (ref leaf ; leaves) {
218 			LeafUpdate(leaf);
219 		}
220 
221         auto staticIndex = cast(BBTree)staticTree;
222         Node *staticRoot = staticIndex !is null ? staticIndex.root : null;
223 
224 		SubtreeSelfQuery(root,staticRoot,func);
225 	
226         if(staticIndex && !staticRoot) 
227 			SpatialIndexCollideStatic(this, staticIndex, func);
228 
229         IncrementStamp();
230 	}
231 
232 	static void SpatialIndexCollideStatic(Tree tree, Tree staticIndex, SpatialIndexQueryFunc func) {
233 		if (staticIndex.length > 0) {
234 			tree.Each((Node* node) {
235 				staticIndex.Query(node.obj, node.obj.BB(), func);
236 			});
237 		}
238 	}
239 
240 	void IncrementStamp()()
241 	{
242 		if (dynamicTree !is null) {
243 			dynamicTree.stamp++;
244 		} else {
245 			stamp++;
246 		}
247 	}
248 
249 	Tree GetMasterTree()() {
250 		if (dynamicTree !is null) {
251 			return dynamicTree;
252 		}
253 		return this;
254 	}
255 
256 	Node * SubtreeInsert(Node *subtree, Node *leaf)
257 	{
258 		if(subtree is null){
259 			return leaf;
260 		} else if(subtree.NodeIsLeaf()){
261 			return NodeNew(leaf, subtree);
262 		} else {
263 			auto cost_a = subtree.b.bb.Area() + rect.MergedArea(subtree.a.bb, leaf.bb);	
264 			auto cost_b = subtree.a.bb.Area() + rect.MergedArea(subtree.b.bb, leaf.bb);
265 
266 			if(cost_a == cost_b){
267 				cost_a = rect.Proximity(subtree.a.bb, leaf.bb);
268 				cost_b = rect.Proximity(subtree.b.bb, leaf.bb);
269 			}
270 
271 			if(cost_b < cost_a){
272 				subtree.NodeSetB(SubtreeInsert(subtree.b, leaf));
273 			} else {	
274 				subtree.NodeSetA(SubtreeInsert(subtree.a, leaf));
275 			}
276 			subtree.bb = rect.Merge(subtree.bb, leaf.bb);
277 
278 			return subtree;
279 		}
280 	}
281 
282 	Node* NodeNew(Node* a, Node* b)
283 	{
284 		Node *node = NodeFromPool();
285 
286 		node.obj = null;	
287 		node.bb = rect.Merge(a.bb, b.bb);
288 		node.parent = null;
289 
290 		node.NodeSetA(a);
291 		node.NodeSetB(b);
292 
293 		return node;
294 	}
295 
296 	rect BB(Indexable obj )
297 	{
298 		auto bb = obj.BB();
299 
300 		/*
301 		cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc;
302 		if(velocityFunc){
303 		cpFloat coef = 0.1f;
304 		cpFloat x = (bb.r - bb.l)*coef;
305 		cpFloat y = (bb.t - bb.b)*coef;
306 
307 		cpVect v = cpvmult(velocityFunc(obj), 0.1f);
308 		return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y));
309 		} else {
310 		return bb;
311 		}
312 		*/
313 		return bb;
314 	}
315 
316 	Node* NewLeaf(Indexable obj ){
317 		auto node = NodeFromPool();
318 		node.obj = obj;
319 		node.bb = BB(obj);
320 
321 		node.parent = null;
322 		node.stamp = 0;
323 
324 		return node;
325 	}
326 }
327 
328 interface Tree {
329 
330 	@property ref TimeStamp stamp();
331 	@property size_t length() const;
332 
333 	void Each(HashSetIterator fnc);
334 
335 	//Contains(obj Indexable) bool
336 	void Insert(Indexable obj);
337 	//Remove(obj Indexable)
338 
339 	//Reindex()
340 	//ReindexObject(obj Indexable)
341 	//ReindexQuery(fnc SpatialIndexQueryFunc)
342 
343 	//TimeStamp Stamp();
344 
345 	void Query(Indexable obj, rect aabb, SpatialIndexQueryFunc fnc);
346 	//SegmentQuery(obj Indexable, a, b vect.Vect, t_exit vect.Float, fnc func())
347 }
348 
349 interface Indexable {
350 	//Hash GetHash();
351 	rect BB();
352 }
353 
354 private struct Node {
355 	public Indexable obj;
356 	rect bb;
357 	Node *parent;
358 
359 	bool NodeIsLeaf()
360 	{
361 		return obj !is null;
362 	}
363 
364 	Node* NodeOther(Node *child)
365 	{
366         return (a == child ? b : a);
367 	}
368 
369 	void NodeSetA()(Node *value)
370 	{
371         a = value;
372         value.parent = &this;
373 	}
374 
375 	void NodeSetB()(Node *value)
376 	{
377         b = value;
378         value.parent = &this;
379 	}
380 
381 	//children
382 	Node* a, b;
383 
384 	//leaf
385 	TimeStamp stamp;
386 };