1 module Engine.Tree.BBTreeCache;
2 
3 import Engine.math;
4 alias ulong TimeStamp;
5 alias ulong Hash;
6 import std.stdio;
7 import Engine.Allocator;
8 
9 alias ulong delegate(Indexable a,Indexable b, ulong collisionID) SpatialIndexQueryFunc;
10 alias void delegate(Node* node)  HashSetIterator;
11 
12 
13 class BBTree : Tree
14 {
15 	ChunkAllocator!(Pair, 100) pairAllocator;
16 	ChunkAllocator!(Node, 100) nodeAllocator;
17 	int allocatedNodes = 0;
18 	int allocatedPair = 0;
19 	int freedNodes = 0;
20 	int freedPair = 0;
21 
22 
23 	Node*[Indexable] leaves;
24 	Node* root;
25 
26 
27 	@property ref TimeStamp stamp() {
28 		return stamp_;
29 	}
30 	TimeStamp stamp_;
31 
32 	Tree staticTree;
33 	Tree dynamicTree;
34 
35 	this(Tree staticTree)
36 	{
37 		if (staticTree !is null) {
38 			this.staticTree = staticTree;
39 		}
40 		stamp_ = 0;
41 	}
42 
43 	@property size_t length() const {
44 		return leaves.length;
45 	}
46 
47 	void Each(HashSetIterator func) {
48 		foreach (Node* node; leaves) {
49 			func(node);
50 		}
51 	}
52 
53 	void Insert(Indexable obj ) {
54 		auto leaf = NewLeaf(obj);
55 		leaves[obj] = leaf;	
56 		this.root = this.SubtreeInsert(this.root, leaf);
57 		leaf.stamp = GetMasterTree().stamp;
58 		LeafAddPairs(leaf);
59 		IncrementStamp();
60 	}
61 
62 	void LeafAddPairs(Node *leaf)
63 	{
64 		if (dynamicTree !is null) {
65 			auto dTree = cast(BBTree)dynamicTree;
66 			if(dTree !is null && dTree.root !is null){
67 				MarkContext context = MarkContext(dTree, null, null);
68 				context.MarkLeafQuery(dTree.root, leaf, true);
69 			}
70         } else {
71 			auto sTree = cast(BBTree)staticTree;
72 			Node *staticRoot = sTree !is null ?  sTree.root : null;
73 			MarkContext context = MarkContext(this, staticRoot, null);
74 			context.MarkLeaf(leaf);
75         }
76 	}
77 
78 	void Query(Indexable obj, rect bb, SpatialIndexQueryFunc func) {
79 		if(root) 
80 			SubtreeQuery(root, obj, bb, func);
81 	}
82 
83 	void SubtreeQuery(Node *subtree, Indexable obj, rect bb, SpatialIndexQueryFunc func)
84 	{
85         if(rect.Intersects(subtree.bb, bb)){
86 			if(subtree.NodeIsLeaf()){
87 				func(obj, subtree.obj, 0);
88 			} else {
89 				SubtreeQuery(subtree.a, obj, bb, func);
90 				SubtreeQuery(subtree.b, obj, bb, func);
91 			}
92         }
93 	}
94 
95 	bool LeafUpdate(Node *leaf)
96 	{
97 		auto rt = root;
98         if(!rect.Contains(leaf.bb, leaf.obj.BB())){
99 			leaf.bb = BB(leaf.obj);
100 
101 			rt = SubtreeRemove(rt, leaf);
102 			root = SubtreeInsert(rt, leaf);
103 
104 			PairsClear(leaf);
105 			leaf.stamp = GetMasterTree.stamp;
106 
107 			return true;
108         } else {
109 			return false;
110         }
111 	}
112 
113 	void PairsClear(Node *leaf)
114 	{	
115         Pair *pair = leaf.pairs;
116         leaf.pairs = null;
117 
118         while(pair !is null){
119 			if(pair.a.leaf == leaf){
120 				Pair *next = pair.a.next;
121 				ThreadUnlink(pair.b);
122 				PairRecycle(pair);
123 				pair = next;
124 			} else {
125 				Pair *next = pair.b.next;
126 				ThreadUnlink(pair.a);
127 				PairRecycle(pair);
128 				pair = next;
129 			}
130         }
131 	}
132 
133 	void ThreadUnlink()(auto ref Thread thread)
134 	{
135         auto next = thread.next;
136         auto prev = thread.prev;
137 
138         if(next){
139 			if(next.a.leaf == thread.leaf) next.a.prev = prev; else next.b.prev = prev;
140         }
141 
142         if(prev){
143 			if(prev.a.leaf == thread.leaf) prev.a.next = next; else prev.b.next = next;
144         } else {
145 			thread.leaf.pairs = next;
146         }
147 	}
148 
149 	Pair* PairFromPool() {
150 		allocatedPair++;
151 		return pairAllocator.allocate();
152 	}
153 
154 	void PairRecycle(Pair *pair)
155 	{
156 		freedPair++;
157 		pair.a.next = null;
158         pairAllocator.free(pair);
159 	}
160 
161 	Node* NodeFromPool() {
162 		allocatedNodes++;
163 		return nodeAllocator.allocate();
164 	}
165 
166 	void NodeRecycle(Node *node)
167 	{
168 		freedNodes++;
169 		node.parent = null;
170 		nodeAllocator.free(node);
171 	}
172 
173 	Node* SubtreeRemove(Node *subtree, Node *leaf)
174 	{
175         if(leaf == subtree){
176 			return null;
177         } else {
178 			Node *parent = leaf.parent;
179 			if(parent == subtree){
180 				Node *other = subtree.NodeOther(leaf);
181 				other.parent = subtree.parent;
182 				NodeRecycle(subtree);
183 				return other;
184 			} else {
185 				NodeReplaceChild(parent.parent, parent, parent.NodeOther(leaf));
186 				return subtree;
187 			}
188         }
189 	}
190 
191 	void NodeReplaceChild(Node *parent, Node *child, Node *value)
192 	{
193 		assert(!parent.NodeIsLeaf(), "Internal Error: Cannot replace child of a leaf.");
194         assert(child == parent.a || child == parent.b, "Internal Error: Node is not a child of parent.");
195 
196         if(parent.a == child){
197 			NodeRecycle(parent.a);
198 			parent.NodeSetA(value);
199         } else {
200 			NodeRecycle(parent.b);
201 			parent.NodeSetB(value);
202         }
203 
204         for(Node *node=parent; node; node = node.parent){
205 			node.bb = rect.Merge(node.a.bb, node.b.bb);
206         }
207 	}
208 
209 	void ReindexQuery(SpatialIndexQueryFunc func)
210 	{
211         if(root is null) return;
212 
213         // LeafUpdate() may modify tree->root. Don't cache it.
214 		foreach (ref leaf ; leaves) {
215 			LeafUpdate(leaf);
216 		}
217 
218         auto staticIndex = cast(BBTree)staticTree;
219         Node *staticRoot = staticIndex !is null ? staticIndex.root : null;
220 
221         MarkContext context = MarkContext(this, staticRoot, func);
222         context.MarkSubtree(root);
223         if(staticIndex && !staticRoot) 
224 			SpatialIndexCollideStatic(this, staticIndex, func);
225 
226         IncrementStamp();
227 	}
228 
229 	static void SpatialIndexCollideStatic(Tree tree, Tree staticIndex, SpatialIndexQueryFunc func) {
230 		if (staticIndex.length > 0) {
231 			tree.Each((Node* node) {
232 				staticIndex.Query(node.obj, node.obj.BB(), func);
233 			});
234 		}
235 	}
236 
237 	void IncrementStamp()()
238 	{
239 		if (dynamicTree !is null) {
240 			dynamicTree.stamp++;
241 		} else {
242 			stamp++;
243 		}
244 	}
245 
246 	Tree GetMasterTree()() {
247 		if (dynamicTree !is null) {
248 			return dynamicTree;
249 		}
250 		return this;
251 	}
252 
253 	Node * SubtreeInsert(Node *subtree, Node *leaf)
254 	{
255 		if(subtree is null){
256 			return leaf;
257 		} else if(subtree.NodeIsLeaf()){
258 			return NodeNew(leaf, subtree);
259 		} else {
260 			auto cost_a = subtree.b.bb.Area() + rect.MergedArea(subtree.a.bb, leaf.bb);	
261 			auto cost_b = subtree.a.bb.Area() + rect.MergedArea(subtree.b.bb, leaf.bb);
262 
263 			if(cost_a == cost_b){
264 				cost_a = rect.Proximity(subtree.a.bb, leaf.bb);
265 				cost_b = rect.Proximity(subtree.b.bb, leaf.bb);
266 			}
267 
268 			if(cost_b < cost_a){
269 				subtree.NodeSetB(SubtreeInsert(subtree.b, leaf));
270 			} else {	
271 				subtree.NodeSetA(SubtreeInsert(subtree.a, leaf));
272 			}
273 			subtree.bb = rect.Merge(subtree.bb, leaf.bb);
274 
275 			return subtree;
276 		}
277 	}
278 
279 	Node* NodeNew(Node* a, Node* b)
280 	{
281 		Node *node = NodeFromPool();
282 
283 		node.obj = null;	
284 		node.bb = rect.Merge(a.bb, b.bb);
285 		node.parent = null;
286 
287 		node.NodeSetA(a);
288 		node.NodeSetB(b);
289 
290 		return node;
291 	}
292 
293 	rect BB(Indexable obj )
294 	{
295 		auto bb = obj.BB();
296 
297 		/*
298 		cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc;
299 		if(velocityFunc){
300 		cpFloat coef = 0.1f;
301 		cpFloat x = (bb.r - bb.l)*coef;
302 		cpFloat y = (bb.t - bb.b)*coef;
303 
304 		cpVect v = cpvmult(velocityFunc(obj), 0.1f);
305 		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));
306 		} else {
307 		return bb;
308 		}
309 		*/
310 		return bb;
311 	}
312 
313 	Node* NewLeaf(Indexable obj ){
314 		auto node = NodeFromPool();
315 		node.obj = obj;
316 		node.bb = BB(obj);
317 
318 		node.parent = null;
319 		node.stamp = 0;
320 		node.pairs = null;
321 
322 		return node;
323 	}
324 
325 	void PairInsert(Node *a, Node *b)
326 	{
327         Pair* nextA = a.pairs, nextB = b.pairs;
328         Pair *pair = PairFromPool();
329 		*pair = Pair(Thread(null, a, nextA),Thread(null, b, nextB), 0);
330 
331         a.pairs = b.pairs = pair;
332 
333         if(nextA !is null){
334 			if(nextA.a.leaf == a) nextA.a.prev = pair; else nextA.b.prev = pair;
335         }
336 
337         if(nextB !is null){
338 			if(nextB.a.leaf == b) nextB.a.prev = pair; else nextB.b.prev = pair;
339         }
340 	}
341 }
342 
343 interface Tree {
344 
345 	@property ref TimeStamp stamp();
346 	@property size_t length() const;
347 
348 	void Each(HashSetIterator fnc);
349 
350 	//Contains(obj Indexable) bool
351 	void Insert(Indexable obj);
352 	//Remove(obj Indexable)
353 
354 	//Reindex()
355 	//ReindexObject(obj Indexable)
356 	//ReindexQuery(fnc SpatialIndexQueryFunc)
357 
358 	//TimeStamp Stamp();
359 
360 	void Query(Indexable obj, rect aabb, SpatialIndexQueryFunc fnc);
361 	//SegmentQuery(obj Indexable, a, b vect.Vect, t_exit vect.Float, fnc func())
362 }
363 
364 struct MarkContext {
365 	BBTree tree;
366 	Node* staticRoot;
367 	SpatialIndexQueryFunc func;
368 
369 
370 	void MarkLeafQuery()(Node *subtree, Node *leaf, bool left)
371 	{
372         if(rect.Intersects(leaf.bb, subtree.bb)){
373 			if(subtree.NodeIsLeaf()) {
374 				if(left){
375 					tree.PairInsert(leaf, subtree);
376 				} else {
377 					if(subtree.stamp < leaf.stamp) 
378 						tree.PairInsert(subtree, leaf);
379 					if (func !is null)
380 						func(leaf.obj, subtree.obj, 0);
381 				}
382 			} else {
383 				MarkLeafQuery(subtree.a, leaf, left);
384 				MarkLeafQuery(subtree.b, leaf, left);
385 			}
386         }
387 	}
388 
389 	void MarkLeaf()(Node *leaf)
390 	{
391         if(leaf.stamp == tree.GetMasterTree().stamp) {
392 			Node *staticRoot = staticRoot;
393 			if(staticRoot !is null) 
394 				MarkLeafQuery(staticRoot, leaf, false);
395 
396 			for(Node *node = leaf; node.parent !is null; node = node.parent){
397 				if(node == node.parent.a){
398 					MarkLeafQuery(node.parent.b, leaf, true);
399 				} else {
400 					MarkLeafQuery(node.parent.a, leaf, false);
401 				}
402 			}
403         } else {
404 			Pair *pair = leaf.pairs;
405 			while(pair !is null){
406 				if(leaf == pair.b.leaf){
407 					if (func !is null)
408 						pair.id = func(pair.a.leaf.obj, leaf.obj, pair.id);
409 					pair = pair.b.next;
410 				} else {
411 					pair = pair.a.next;
412 				}
413 			}
414         }
415 	}
416 
417 	void MarkSubtree()(Node *subtree)
418 	{
419         if(subtree.NodeIsLeaf()){
420 			MarkLeaf(subtree);
421         } else {
422 			MarkSubtree(subtree.a);
423 			MarkSubtree(subtree.b); // TODO: Force TCO here?
424         }
425 	}
426 
427 };
428 
429 interface Indexable {
430 	//Hash GetHash();
431 	rect BB();
432 }
433 
434 struct Thread  {
435 	Pair* prev;
436 	Node* leaf;
437 	Pair* next;
438 }
439 
440 struct Pair {
441 	Thread a, b; 
442 	ulong id;
443 }
444 
445 struct Node {
446 	Indexable obj;
447 	rect bb;
448 	Node *parent;
449 
450 	bool NodeIsLeaf()
451 	{
452 		return obj !is null;
453 	}
454 
455 	Node* NodeOther(Node *child)
456 	{
457         return (a == child ? b : a);
458 	}
459 
460 	void NodeSetA()(Node *value)
461 	{
462         a = value;
463         value.parent = &this;
464 	}
465 
466 	void NodeSetB()(Node *value)
467 	{
468         b = value;
469         value.parent = &this;
470 	}
471 
472 	//children
473 	Node* a, b;
474 
475 	//leaf
476 	TimeStamp stamp;
477 	Pair* pairs;
478 };