1// generated; DO NOT EDIT!
2
3package rtree
4
5import "math"
6
7type Iterator func(item Item) bool
8type Item interface {
9	Rect(ctx interface{}) (min []float64, max []float64)
10}
11
12type RTree struct {
13	ctx  interface{}
14	tr1  *d1RTree
15	tr2  *d2RTree
16	tr3  *d3RTree
17	tr4  *d4RTree
18	tr5  *d5RTree
19	tr6  *d6RTree
20	tr7  *d7RTree
21	tr8  *d8RTree
22	tr9  *d9RTree
23	tr10 *d10RTree
24	tr11 *d11RTree
25	tr12 *d12RTree
26	tr13 *d13RTree
27	tr14 *d14RTree
28	tr15 *d15RTree
29	tr16 *d16RTree
30	tr17 *d17RTree
31	tr18 *d18RTree
32	tr19 *d19RTree
33	tr20 *d20RTree
34}
35
36func New(ctx interface{}) *RTree {
37	return &RTree{
38		ctx:  ctx,
39		tr1:  d1New(),
40		tr2:  d2New(),
41		tr3:  d3New(),
42		tr4:  d4New(),
43		tr5:  d5New(),
44		tr6:  d6New(),
45		tr7:  d7New(),
46		tr8:  d8New(),
47		tr9:  d9New(),
48		tr10: d10New(),
49		tr11: d11New(),
50		tr12: d12New(),
51		tr13: d13New(),
52		tr14: d14New(),
53		tr15: d15New(),
54		tr16: d16New(),
55		tr17: d17New(),
56		tr18: d18New(),
57		tr19: d19New(),
58		tr20: d20New(),
59	}
60}
61
62func (tr *RTree) Insert(item Item) {
63	if item == nil {
64		panic("nil item being added to RTree")
65	}
66	min, max := item.Rect(tr.ctx)
67	if len(min) != len(max) {
68		return // just return
69		panic("invalid item rectangle")
70	}
71	switch len(min) {
72	default:
73		return // just return
74		panic("invalid dimension")
75	case 1:
76		var amin, amax [1]float64
77		for i := 0; i < len(min); i++ {
78			amin[i], amax[i] = min[i], max[i]
79		}
80		tr.tr1.Insert(amin, amax, item)
81	case 2:
82		var amin, amax [2]float64
83		for i := 0; i < len(min); i++ {
84			amin[i], amax[i] = min[i], max[i]
85		}
86		tr.tr2.Insert(amin, amax, item)
87	case 3:
88		var amin, amax [3]float64
89		for i := 0; i < len(min); i++ {
90			amin[i], amax[i] = min[i], max[i]
91		}
92		tr.tr3.Insert(amin, amax, item)
93	case 4:
94		var amin, amax [4]float64
95		for i := 0; i < len(min); i++ {
96			amin[i], amax[i] = min[i], max[i]
97		}
98		tr.tr4.Insert(amin, amax, item)
99	case 5:
100		var amin, amax [5]float64
101		for i := 0; i < len(min); i++ {
102			amin[i], amax[i] = min[i], max[i]
103		}
104		tr.tr5.Insert(amin, amax, item)
105	case 6:
106		var amin, amax [6]float64
107		for i := 0; i < len(min); i++ {
108			amin[i], amax[i] = min[i], max[i]
109		}
110		tr.tr6.Insert(amin, amax, item)
111	case 7:
112		var amin, amax [7]float64
113		for i := 0; i < len(min); i++ {
114			amin[i], amax[i] = min[i], max[i]
115		}
116		tr.tr7.Insert(amin, amax, item)
117	case 8:
118		var amin, amax [8]float64
119		for i := 0; i < len(min); i++ {
120			amin[i], amax[i] = min[i], max[i]
121		}
122		tr.tr8.Insert(amin, amax, item)
123	case 9:
124		var amin, amax [9]float64
125		for i := 0; i < len(min); i++ {
126			amin[i], amax[i] = min[i], max[i]
127		}
128		tr.tr9.Insert(amin, amax, item)
129	case 10:
130		var amin, amax [10]float64
131		for i := 0; i < len(min); i++ {
132			amin[i], amax[i] = min[i], max[i]
133		}
134		tr.tr10.Insert(amin, amax, item)
135	case 11:
136		var amin, amax [11]float64
137		for i := 0; i < len(min); i++ {
138			amin[i], amax[i] = min[i], max[i]
139		}
140		tr.tr11.Insert(amin, amax, item)
141	case 12:
142		var amin, amax [12]float64
143		for i := 0; i < len(min); i++ {
144			amin[i], amax[i] = min[i], max[i]
145		}
146		tr.tr12.Insert(amin, amax, item)
147	case 13:
148		var amin, amax [13]float64
149		for i := 0; i < len(min); i++ {
150			amin[i], amax[i] = min[i], max[i]
151		}
152		tr.tr13.Insert(amin, amax, item)
153	case 14:
154		var amin, amax [14]float64
155		for i := 0; i < len(min); i++ {
156			amin[i], amax[i] = min[i], max[i]
157		}
158		tr.tr14.Insert(amin, amax, item)
159	case 15:
160		var amin, amax [15]float64
161		for i := 0; i < len(min); i++ {
162			amin[i], amax[i] = min[i], max[i]
163		}
164		tr.tr15.Insert(amin, amax, item)
165	case 16:
166		var amin, amax [16]float64
167		for i := 0; i < len(min); i++ {
168			amin[i], amax[i] = min[i], max[i]
169		}
170		tr.tr16.Insert(amin, amax, item)
171	case 17:
172		var amin, amax [17]float64
173		for i := 0; i < len(min); i++ {
174			amin[i], amax[i] = min[i], max[i]
175		}
176		tr.tr17.Insert(amin, amax, item)
177	case 18:
178		var amin, amax [18]float64
179		for i := 0; i < len(min); i++ {
180			amin[i], amax[i] = min[i], max[i]
181		}
182		tr.tr18.Insert(amin, amax, item)
183	case 19:
184		var amin, amax [19]float64
185		for i := 0; i < len(min); i++ {
186			amin[i], amax[i] = min[i], max[i]
187		}
188		tr.tr19.Insert(amin, amax, item)
189	case 20:
190		var amin, amax [20]float64
191		for i := 0; i < len(min); i++ {
192			amin[i], amax[i] = min[i], max[i]
193		}
194		tr.tr20.Insert(amin, amax, item)
195	}
196}
197
198func (tr *RTree) Remove(item Item) {
199	if item == nil {
200		panic("nil item being added to RTree")
201	}
202	min, max := item.Rect(tr.ctx)
203	if len(min) != len(max) {
204		return // just return
205		panic("invalid item rectangle")
206	}
207	switch len(min) {
208	default:
209		return // just return
210		panic("invalid dimension")
211	case 1:
212		var amin, amax [1]float64
213		for i := 0; i < len(min); i++ {
214			amin[i], amax[i] = min[i], max[i]
215		}
216		tr.tr1.Remove(amin, amax, item)
217	case 2:
218		var amin, amax [2]float64
219		for i := 0; i < len(min); i++ {
220			amin[i], amax[i] = min[i], max[i]
221		}
222		tr.tr2.Remove(amin, amax, item)
223	case 3:
224		var amin, amax [3]float64
225		for i := 0; i < len(min); i++ {
226			amin[i], amax[i] = min[i], max[i]
227		}
228		tr.tr3.Remove(amin, amax, item)
229	case 4:
230		var amin, amax [4]float64
231		for i := 0; i < len(min); i++ {
232			amin[i], amax[i] = min[i], max[i]
233		}
234		tr.tr4.Remove(amin, amax, item)
235	case 5:
236		var amin, amax [5]float64
237		for i := 0; i < len(min); i++ {
238			amin[i], amax[i] = min[i], max[i]
239		}
240		tr.tr5.Remove(amin, amax, item)
241	case 6:
242		var amin, amax [6]float64
243		for i := 0; i < len(min); i++ {
244			amin[i], amax[i] = min[i], max[i]
245		}
246		tr.tr6.Remove(amin, amax, item)
247	case 7:
248		var amin, amax [7]float64
249		for i := 0; i < len(min); i++ {
250			amin[i], amax[i] = min[i], max[i]
251		}
252		tr.tr7.Remove(amin, amax, item)
253	case 8:
254		var amin, amax [8]float64
255		for i := 0; i < len(min); i++ {
256			amin[i], amax[i] = min[i], max[i]
257		}
258		tr.tr8.Remove(amin, amax, item)
259	case 9:
260		var amin, amax [9]float64
261		for i := 0; i < len(min); i++ {
262			amin[i], amax[i] = min[i], max[i]
263		}
264		tr.tr9.Remove(amin, amax, item)
265	case 10:
266		var amin, amax [10]float64
267		for i := 0; i < len(min); i++ {
268			amin[i], amax[i] = min[i], max[i]
269		}
270		tr.tr10.Remove(amin, amax, item)
271	case 11:
272		var amin, amax [11]float64
273		for i := 0; i < len(min); i++ {
274			amin[i], amax[i] = min[i], max[i]
275		}
276		tr.tr11.Remove(amin, amax, item)
277	case 12:
278		var amin, amax [12]float64
279		for i := 0; i < len(min); i++ {
280			amin[i], amax[i] = min[i], max[i]
281		}
282		tr.tr12.Remove(amin, amax, item)
283	case 13:
284		var amin, amax [13]float64
285		for i := 0; i < len(min); i++ {
286			amin[i], amax[i] = min[i], max[i]
287		}
288		tr.tr13.Remove(amin, amax, item)
289	case 14:
290		var amin, amax [14]float64
291		for i := 0; i < len(min); i++ {
292			amin[i], amax[i] = min[i], max[i]
293		}
294		tr.tr14.Remove(amin, amax, item)
295	case 15:
296		var amin, amax [15]float64
297		for i := 0; i < len(min); i++ {
298			amin[i], amax[i] = min[i], max[i]
299		}
300		tr.tr15.Remove(amin, amax, item)
301	case 16:
302		var amin, amax [16]float64
303		for i := 0; i < len(min); i++ {
304			amin[i], amax[i] = min[i], max[i]
305		}
306		tr.tr16.Remove(amin, amax, item)
307	case 17:
308		var amin, amax [17]float64
309		for i := 0; i < len(min); i++ {
310			amin[i], amax[i] = min[i], max[i]
311		}
312		tr.tr17.Remove(amin, amax, item)
313	case 18:
314		var amin, amax [18]float64
315		for i := 0; i < len(min); i++ {
316			amin[i], amax[i] = min[i], max[i]
317		}
318		tr.tr18.Remove(amin, amax, item)
319	case 19:
320		var amin, amax [19]float64
321		for i := 0; i < len(min); i++ {
322			amin[i], amax[i] = min[i], max[i]
323		}
324		tr.tr19.Remove(amin, amax, item)
325	case 20:
326		var amin, amax [20]float64
327		for i := 0; i < len(min); i++ {
328			amin[i], amax[i] = min[i], max[i]
329		}
330		tr.tr20.Remove(amin, amax, item)
331	}
332}
333func (tr *RTree) Reset() {
334	tr.tr1 = d1New()
335	tr.tr2 = d2New()
336	tr.tr3 = d3New()
337	tr.tr4 = d4New()
338	tr.tr5 = d5New()
339	tr.tr6 = d6New()
340	tr.tr7 = d7New()
341	tr.tr8 = d8New()
342	tr.tr9 = d9New()
343	tr.tr10 = d10New()
344	tr.tr11 = d11New()
345	tr.tr12 = d12New()
346	tr.tr13 = d13New()
347	tr.tr14 = d14New()
348	tr.tr15 = d15New()
349	tr.tr16 = d16New()
350	tr.tr17 = d17New()
351	tr.tr18 = d18New()
352	tr.tr19 = d19New()
353	tr.tr20 = d20New()
354}
355func (tr *RTree) Count() int {
356	count := 0
357	count += tr.tr1.Count()
358	count += tr.tr2.Count()
359	count += tr.tr3.Count()
360	count += tr.tr4.Count()
361	count += tr.tr5.Count()
362	count += tr.tr6.Count()
363	count += tr.tr7.Count()
364	count += tr.tr8.Count()
365	count += tr.tr9.Count()
366	count += tr.tr10.Count()
367	count += tr.tr11.Count()
368	count += tr.tr12.Count()
369	count += tr.tr13.Count()
370	count += tr.tr14.Count()
371	count += tr.tr15.Count()
372	count += tr.tr16.Count()
373	count += tr.tr17.Count()
374	count += tr.tr18.Count()
375	count += tr.tr19.Count()
376	count += tr.tr20.Count()
377	return count
378}
379func (tr *RTree) Search(bounds Item, iter Iterator) {
380	if bounds == nil {
381		panic("nil bounds being used for search")
382	}
383	min, max := bounds.Rect(tr.ctx)
384	if len(min) != len(max) {
385		return // just return
386		panic("invalid item rectangle")
387	}
388	switch len(min) {
389	default:
390		return // just return
391		panic("invalid dimension")
392	case 1:
393	case 2:
394	case 3:
395	case 4:
396	case 5:
397	case 6:
398	case 7:
399	case 8:
400	case 9:
401	case 10:
402	case 11:
403	case 12:
404	case 13:
405	case 14:
406	case 15:
407	case 16:
408	case 17:
409	case 18:
410	case 19:
411	case 20:
412	}
413	if !tr.search1(min, max, iter) {
414		return
415	}
416	if !tr.search2(min, max, iter) {
417		return
418	}
419	if !tr.search3(min, max, iter) {
420		return
421	}
422	if !tr.search4(min, max, iter) {
423		return
424	}
425	if !tr.search5(min, max, iter) {
426		return
427	}
428	if !tr.search6(min, max, iter) {
429		return
430	}
431	if !tr.search7(min, max, iter) {
432		return
433	}
434	if !tr.search8(min, max, iter) {
435		return
436	}
437	if !tr.search9(min, max, iter) {
438		return
439	}
440	if !tr.search10(min, max, iter) {
441		return
442	}
443	if !tr.search11(min, max, iter) {
444		return
445	}
446	if !tr.search12(min, max, iter) {
447		return
448	}
449	if !tr.search13(min, max, iter) {
450		return
451	}
452	if !tr.search14(min, max, iter) {
453		return
454	}
455	if !tr.search15(min, max, iter) {
456		return
457	}
458	if !tr.search16(min, max, iter) {
459		return
460	}
461	if !tr.search17(min, max, iter) {
462		return
463	}
464	if !tr.search18(min, max, iter) {
465		return
466	}
467	if !tr.search19(min, max, iter) {
468		return
469	}
470	if !tr.search20(min, max, iter) {
471		return
472	}
473}
474
475func (tr *RTree) search1(min, max []float64, iter Iterator) bool {
476	var amin, amax [1]float64
477	for i := 0; i < 1; i++ {
478		if i < len(min) {
479			amin[i] = min[i]
480			amax[i] = max[i]
481		} else {
482			amin[i] = math.Inf(-1)
483			amax[i] = math.Inf(+1)
484		}
485	}
486	ended := false
487	tr.tr1.Search(amin, amax, func(dataID interface{}) bool {
488		if !iter(dataID.(Item)) {
489			ended = true
490			return false
491		}
492		return true
493	})
494	return !ended
495}
496
497func (tr *RTree) search2(min, max []float64, iter Iterator) bool {
498	var amin, amax [2]float64
499	for i := 0; i < 2; i++ {
500		if i < len(min) {
501			amin[i] = min[i]
502			amax[i] = max[i]
503		} else {
504			amin[i] = math.Inf(-1)
505			amax[i] = math.Inf(+1)
506		}
507	}
508	ended := false
509	tr.tr2.Search(amin, amax, func(dataID interface{}) bool {
510		if !iter(dataID.(Item)) {
511			ended = true
512			return false
513		}
514		return true
515	})
516	return !ended
517}
518
519func (tr *RTree) search3(min, max []float64, iter Iterator) bool {
520	var amin, amax [3]float64
521	for i := 0; i < 3; i++ {
522		if i < len(min) {
523			amin[i] = min[i]
524			amax[i] = max[i]
525		} else {
526			amin[i] = math.Inf(-1)
527			amax[i] = math.Inf(+1)
528		}
529	}
530	ended := false
531	tr.tr3.Search(amin, amax, func(dataID interface{}) bool {
532		if !iter(dataID.(Item)) {
533			ended = true
534			return false
535		}
536		return true
537	})
538	return !ended
539}
540
541func (tr *RTree) search4(min, max []float64, iter Iterator) bool {
542	var amin, amax [4]float64
543	for i := 0; i < 4; i++ {
544		if i < len(min) {
545			amin[i] = min[i]
546			amax[i] = max[i]
547		} else {
548			amin[i] = math.Inf(-1)
549			amax[i] = math.Inf(+1)
550		}
551	}
552	ended := false
553	tr.tr4.Search(amin, amax, func(dataID interface{}) bool {
554		if !iter(dataID.(Item)) {
555			ended = true
556			return false
557		}
558		return true
559	})
560	return !ended
561}
562
563func (tr *RTree) search5(min, max []float64, iter Iterator) bool {
564	var amin, amax [5]float64
565	for i := 0; i < 5; i++ {
566		if i < len(min) {
567			amin[i] = min[i]
568			amax[i] = max[i]
569		} else {
570			amin[i] = math.Inf(-1)
571			amax[i] = math.Inf(+1)
572		}
573	}
574	ended := false
575	tr.tr5.Search(amin, amax, func(dataID interface{}) bool {
576		if !iter(dataID.(Item)) {
577			ended = true
578			return false
579		}
580		return true
581	})
582	return !ended
583}
584
585func (tr *RTree) search6(min, max []float64, iter Iterator) bool {
586	var amin, amax [6]float64
587	for i := 0; i < 6; i++ {
588		if i < len(min) {
589			amin[i] = min[i]
590			amax[i] = max[i]
591		} else {
592			amin[i] = math.Inf(-1)
593			amax[i] = math.Inf(+1)
594		}
595	}
596	ended := false
597	tr.tr6.Search(amin, amax, func(dataID interface{}) bool {
598		if !iter(dataID.(Item)) {
599			ended = true
600			return false
601		}
602		return true
603	})
604	return !ended
605}
606
607func (tr *RTree) search7(min, max []float64, iter Iterator) bool {
608	var amin, amax [7]float64
609	for i := 0; i < 7; i++ {
610		if i < len(min) {
611			amin[i] = min[i]
612			amax[i] = max[i]
613		} else {
614			amin[i] = math.Inf(-1)
615			amax[i] = math.Inf(+1)
616		}
617	}
618	ended := false
619	tr.tr7.Search(amin, amax, func(dataID interface{}) bool {
620		if !iter(dataID.(Item)) {
621			ended = true
622			return false
623		}
624		return true
625	})
626	return !ended
627}
628
629func (tr *RTree) search8(min, max []float64, iter Iterator) bool {
630	var amin, amax [8]float64
631	for i := 0; i < 8; i++ {
632		if i < len(min) {
633			amin[i] = min[i]
634			amax[i] = max[i]
635		} else {
636			amin[i] = math.Inf(-1)
637			amax[i] = math.Inf(+1)
638		}
639	}
640	ended := false
641	tr.tr8.Search(amin, amax, func(dataID interface{}) bool {
642		if !iter(dataID.(Item)) {
643			ended = true
644			return false
645		}
646		return true
647	})
648	return !ended
649}
650
651func (tr *RTree) search9(min, max []float64, iter Iterator) bool {
652	var amin, amax [9]float64
653	for i := 0; i < 9; i++ {
654		if i < len(min) {
655			amin[i] = min[i]
656			amax[i] = max[i]
657		} else {
658			amin[i] = math.Inf(-1)
659			amax[i] = math.Inf(+1)
660		}
661	}
662	ended := false
663	tr.tr9.Search(amin, amax, func(dataID interface{}) bool {
664		if !iter(dataID.(Item)) {
665			ended = true
666			return false
667		}
668		return true
669	})
670	return !ended
671}
672
673func (tr *RTree) search10(min, max []float64, iter Iterator) bool {
674	var amin, amax [10]float64
675	for i := 0; i < 10; i++ {
676		if i < len(min) {
677			amin[i] = min[i]
678			amax[i] = max[i]
679		} else {
680			amin[i] = math.Inf(-1)
681			amax[i] = math.Inf(+1)
682		}
683	}
684	ended := false
685	tr.tr10.Search(amin, amax, func(dataID interface{}) bool {
686		if !iter(dataID.(Item)) {
687			ended = true
688			return false
689		}
690		return true
691	})
692	return !ended
693}
694
695func (tr *RTree) search11(min, max []float64, iter Iterator) bool {
696	var amin, amax [11]float64
697	for i := 0; i < 11; i++ {
698		if i < len(min) {
699			amin[i] = min[i]
700			amax[i] = max[i]
701		} else {
702			amin[i] = math.Inf(-1)
703			amax[i] = math.Inf(+1)
704		}
705	}
706	ended := false
707	tr.tr11.Search(amin, amax, func(dataID interface{}) bool {
708		if !iter(dataID.(Item)) {
709			ended = true
710			return false
711		}
712		return true
713	})
714	return !ended
715}
716
717func (tr *RTree) search12(min, max []float64, iter Iterator) bool {
718	var amin, amax [12]float64
719	for i := 0; i < 12; i++ {
720		if i < len(min) {
721			amin[i] = min[i]
722			amax[i] = max[i]
723		} else {
724			amin[i] = math.Inf(-1)
725			amax[i] = math.Inf(+1)
726		}
727	}
728	ended := false
729	tr.tr12.Search(amin, amax, func(dataID interface{}) bool {
730		if !iter(dataID.(Item)) {
731			ended = true
732			return false
733		}
734		return true
735	})
736	return !ended
737}
738
739func (tr *RTree) search13(min, max []float64, iter Iterator) bool {
740	var amin, amax [13]float64
741	for i := 0; i < 13; i++ {
742		if i < len(min) {
743			amin[i] = min[i]
744			amax[i] = max[i]
745		} else {
746			amin[i] = math.Inf(-1)
747			amax[i] = math.Inf(+1)
748		}
749	}
750	ended := false
751	tr.tr13.Search(amin, amax, func(dataID interface{}) bool {
752		if !iter(dataID.(Item)) {
753			ended = true
754			return false
755		}
756		return true
757	})
758	return !ended
759}
760
761func (tr *RTree) search14(min, max []float64, iter Iterator) bool {
762	var amin, amax [14]float64
763	for i := 0; i < 14; i++ {
764		if i < len(min) {
765			amin[i] = min[i]
766			amax[i] = max[i]
767		} else {
768			amin[i] = math.Inf(-1)
769			amax[i] = math.Inf(+1)
770		}
771	}
772	ended := false
773	tr.tr14.Search(amin, amax, func(dataID interface{}) bool {
774		if !iter(dataID.(Item)) {
775			ended = true
776			return false
777		}
778		return true
779	})
780	return !ended
781}
782
783func (tr *RTree) search15(min, max []float64, iter Iterator) bool {
784	var amin, amax [15]float64
785	for i := 0; i < 15; i++ {
786		if i < len(min) {
787			amin[i] = min[i]
788			amax[i] = max[i]
789		} else {
790			amin[i] = math.Inf(-1)
791			amax[i] = math.Inf(+1)
792		}
793	}
794	ended := false
795	tr.tr15.Search(amin, amax, func(dataID interface{}) bool {
796		if !iter(dataID.(Item)) {
797			ended = true
798			return false
799		}
800		return true
801	})
802	return !ended
803}
804
805func (tr *RTree) search16(min, max []float64, iter Iterator) bool {
806	var amin, amax [16]float64
807	for i := 0; i < 16; i++ {
808		if i < len(min) {
809			amin[i] = min[i]
810			amax[i] = max[i]
811		} else {
812			amin[i] = math.Inf(-1)
813			amax[i] = math.Inf(+1)
814		}
815	}
816	ended := false
817	tr.tr16.Search(amin, amax, func(dataID interface{}) bool {
818		if !iter(dataID.(Item)) {
819			ended = true
820			return false
821		}
822		return true
823	})
824	return !ended
825}
826
827func (tr *RTree) search17(min, max []float64, iter Iterator) bool {
828	var amin, amax [17]float64
829	for i := 0; i < 17; i++ {
830		if i < len(min) {
831			amin[i] = min[i]
832			amax[i] = max[i]
833		} else {
834			amin[i] = math.Inf(-1)
835			amax[i] = math.Inf(+1)
836		}
837	}
838	ended := false
839	tr.tr17.Search(amin, amax, func(dataID interface{}) bool {
840		if !iter(dataID.(Item)) {
841			ended = true
842			return false
843		}
844		return true
845	})
846	return !ended
847}
848
849func (tr *RTree) search18(min, max []float64, iter Iterator) bool {
850	var amin, amax [18]float64
851	for i := 0; i < 18; i++ {
852		if i < len(min) {
853			amin[i] = min[i]
854			amax[i] = max[i]
855		} else {
856			amin[i] = math.Inf(-1)
857			amax[i] = math.Inf(+1)
858		}
859	}
860	ended := false
861	tr.tr18.Search(amin, amax, func(dataID interface{}) bool {
862		if !iter(dataID.(Item)) {
863			ended = true
864			return false
865		}
866		return true
867	})
868	return !ended
869}
870
871func (tr *RTree) search19(min, max []float64, iter Iterator) bool {
872	var amin, amax [19]float64
873	for i := 0; i < 19; i++ {
874		if i < len(min) {
875			amin[i] = min[i]
876			amax[i] = max[i]
877		} else {
878			amin[i] = math.Inf(-1)
879			amax[i] = math.Inf(+1)
880		}
881	}
882	ended := false
883	tr.tr19.Search(amin, amax, func(dataID interface{}) bool {
884		if !iter(dataID.(Item)) {
885			ended = true
886			return false
887		}
888		return true
889	})
890	return !ended
891}
892
893func (tr *RTree) search20(min, max []float64, iter Iterator) bool {
894	var amin, amax [20]float64
895	for i := 0; i < 20; i++ {
896		if i < len(min) {
897			amin[i] = min[i]
898			amax[i] = max[i]
899		} else {
900			amin[i] = math.Inf(-1)
901			amax[i] = math.Inf(+1)
902		}
903	}
904	ended := false
905	tr.tr20.Search(amin, amax, func(dataID interface{}) bool {
906		if !iter(dataID.(Item)) {
907			ended = true
908			return false
909		}
910		return true
911	})
912	return !ended
913}
914
915func d1fmin(a, b float64) float64 {
916	if a < b {
917		return a
918	}
919	return b
920}
921func d1fmax(a, b float64) float64 {
922	if a > b {
923		return a
924	}
925	return b
926}
927
928const (
929	d1numDims            = 1
930	d1maxNodes           = 8
931	d1minNodes           = d1maxNodes / 2
932	d1useSphericalVolume = true // Better split classification, may be slower on some systems
933)
934
935var d1unitSphereVolume = []float64{
936	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
937	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
938	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
939	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
940	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
941	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
942	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
943}[d1numDims]
944
945type d1RTree struct {
946	root *d1nodeT ///< Root of tree
947}
948
949/// Minimal bounding rectangle (n-dimensional)
950type d1rectT struct {
951	min [d1numDims]float64 ///< Min dimensions of bounding box
952	max [d1numDims]float64 ///< Max dimensions of bounding box
953}
954
955/// May be data or may be another subtree
956/// The parents level determines this.
957/// If the parents level is 0, then this is data
958type d1branchT struct {
959	rect  d1rectT     ///< Bounds
960	child *d1nodeT    ///< Child node
961	data  interface{} ///< Data Id or Ptr
962}
963
964/// d1nodeT for each branch level
965type d1nodeT struct {
966	count  int                   ///< Count
967	level  int                   ///< Leaf is zero, others positive
968	branch [d1maxNodes]d1branchT ///< Branch
969}
970
971func (node *d1nodeT) isInternalNode() bool {
972	return (node.level > 0) // Not a leaf, but a internal node
973}
974func (node *d1nodeT) isLeaf() bool {
975	return (node.level == 0) // A leaf, contains data
976}
977
978/// A link list of nodes for reinsertion after a delete operation
979type d1listNodeT struct {
980	next *d1listNodeT ///< Next in list
981	node *d1nodeT     ///< Node
982}
983
984const d1notTaken = -1 // indicates that position
985
986/// Variables for finding a split partition
987type d1partitionVarsT struct {
988	partition [d1maxNodes + 1]int
989	total     int
990	minFill   int
991	count     [2]int
992	cover     [2]d1rectT
993	area      [2]float64
994
995	branchBuf      [d1maxNodes + 1]d1branchT
996	branchCount    int
997	coverSplit     d1rectT
998	coverSplitArea float64
999}
1000
1001func d1New() *d1RTree {
1002	// We only support machine word size simple data type eg. integer index or object pointer.
1003	// Since we are storing as union with non data branch
1004	return &d1RTree{
1005		root: &d1nodeT{},
1006	}
1007}
1008
1009/// Insert entry
1010/// \param a_min Min of bounding rect
1011/// \param a_max Max of bounding rect
1012/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
1013func (tr *d1RTree) Insert(min, max [d1numDims]float64, dataId interface{}) {
1014	var branch d1branchT
1015	branch.data = dataId
1016	for axis := 0; axis < d1numDims; axis++ {
1017		branch.rect.min[axis] = min[axis]
1018		branch.rect.max[axis] = max[axis]
1019	}
1020	d1insertRect(&branch, &tr.root, 0)
1021}
1022
1023/// Remove entry
1024/// \param a_min Min of bounding rect
1025/// \param a_max Max of bounding rect
1026/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
1027func (tr *d1RTree) Remove(min, max [d1numDims]float64, dataId interface{}) {
1028	var rect d1rectT
1029	for axis := 0; axis < d1numDims; axis++ {
1030		rect.min[axis] = min[axis]
1031		rect.max[axis] = max[axis]
1032	}
1033	d1removeRect(&rect, dataId, &tr.root)
1034}
1035
1036/// Find all within d1search rectangle
1037/// \param a_min Min of d1search bounding rect
1038/// \param a_max Max of d1search bounding rect
1039/// \param a_searchResult d1search result array.  Caller should set grow size. Function will reset, not append to array.
1040/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
1041/// \param a_context User context to pass as parameter to a_resultCallback
1042/// \return Returns the number of entries found
1043func (tr *d1RTree) Search(min, max [d1numDims]float64, resultCallback func(data interface{}) bool) int {
1044	var rect d1rectT
1045	for axis := 0; axis < d1numDims; axis++ {
1046		rect.min[axis] = min[axis]
1047		rect.max[axis] = max[axis]
1048	}
1049	foundCount, _ := d1search(tr.root, rect, 0, resultCallback)
1050	return foundCount
1051}
1052
1053/// Count the data elements in this container.  This is slow as no internal counter is maintained.
1054func (tr *d1RTree) Count() int {
1055	var count int
1056	d1countRec(tr.root, &count)
1057	return count
1058}
1059
1060/// Remove all entries from tree
1061func (tr *d1RTree) RemoveAll() {
1062	// Delete all existing nodes
1063	tr.root = &d1nodeT{}
1064}
1065
1066func d1countRec(node *d1nodeT, count *int) {
1067	if node.isInternalNode() { // not a leaf node
1068		for index := 0; index < node.count; index++ {
1069			d1countRec(node.branch[index].child, count)
1070		}
1071	} else { // A leaf node
1072		*count += node.count
1073	}
1074}
1075
1076// Inserts a new data rectangle into the index structure.
1077// Recursively descends tree, propagates splits back up.
1078// Returns 0 if node was not split.  Old node updated.
1079// If node was split, returns 1 and sets the pointer pointed to by
1080// new_node to point to the new node.  Old node updated to become one of two.
1081// The level argument specifies the number of steps up from the leaf
1082// level to insert; e.g. a data rectangle goes in at level = 0.
1083func d1insertRectRec(branch *d1branchT, node *d1nodeT, newNode **d1nodeT, level int) bool {
1084	// recurse until we reach the correct level for the new record. data records
1085	// will always be called with a_level == 0 (leaf)
1086	if node.level > level {
1087		// Still above level for insertion, go down tree recursively
1088		var otherNode *d1nodeT
1089		//var newBranch d1branchT
1090
1091		// find the optimal branch for this record
1092		index := d1pickBranch(&branch.rect, node)
1093
1094		// recursively insert this record into the picked branch
1095		childWasSplit := d1insertRectRec(branch, node.branch[index].child, &otherNode, level)
1096
1097		if !childWasSplit {
1098			// Child was not split. Merge the bounding box of the new record with the
1099			// existing bounding box
1100			node.branch[index].rect = d1combineRect(&branch.rect, &(node.branch[index].rect))
1101			return false
1102		} else {
1103			// Child was split. The old branches are now re-partitioned to two nodes
1104			// so we have to re-calculate the bounding boxes of each node
1105			node.branch[index].rect = d1nodeCover(node.branch[index].child)
1106			var newBranch d1branchT
1107			newBranch.child = otherNode
1108			newBranch.rect = d1nodeCover(otherNode)
1109
1110			// The old node is already a child of a_node. Now add the newly-created
1111			// node to a_node as well. a_node might be split because of that.
1112			return d1addBranch(&newBranch, node, newNode)
1113		}
1114	} else if node.level == level {
1115		// We have reached level for insertion. Add rect, split if necessary
1116		return d1addBranch(branch, node, newNode)
1117	} else {
1118		// Should never occur
1119		return false
1120	}
1121}
1122
1123// Insert a data rectangle into an index structure.
1124// d1insertRect provides for splitting the root;
1125// returns 1 if root was split, 0 if it was not.
1126// The level argument specifies the number of steps up from the leaf
1127// level to insert; e.g. a data rectangle goes in at level = 0.
1128// InsertRect2 does the recursion.
1129//
1130func d1insertRect(branch *d1branchT, root **d1nodeT, level int) bool {
1131	var newNode *d1nodeT
1132
1133	if d1insertRectRec(branch, *root, &newNode, level) { // Root split
1134
1135		// Grow tree taller and new root
1136		newRoot := &d1nodeT{}
1137		newRoot.level = (*root).level + 1
1138
1139		var newBranch d1branchT
1140
1141		// add old root node as a child of the new root
1142		newBranch.rect = d1nodeCover(*root)
1143		newBranch.child = *root
1144		d1addBranch(&newBranch, newRoot, nil)
1145
1146		// add the split node as a child of the new root
1147		newBranch.rect = d1nodeCover(newNode)
1148		newBranch.child = newNode
1149		d1addBranch(&newBranch, newRoot, nil)
1150
1151		// set the new root as the root node
1152		*root = newRoot
1153
1154		return true
1155	}
1156	return false
1157}
1158
1159// Find the smallest rectangle that includes all rectangles in branches of a node.
1160func d1nodeCover(node *d1nodeT) d1rectT {
1161	rect := node.branch[0].rect
1162	for index := 1; index < node.count; index++ {
1163		rect = d1combineRect(&rect, &(node.branch[index].rect))
1164	}
1165	return rect
1166}
1167
1168// Add a branch to a node.  Split the node if necessary.
1169// Returns 0 if node not split.  Old node updated.
1170// Returns 1 if node split, sets *new_node to address of new node.
1171// Old node updated, becomes one of two.
1172func d1addBranch(branch *d1branchT, node *d1nodeT, newNode **d1nodeT) bool {
1173	if node.count < d1maxNodes { // Split won't be necessary
1174		node.branch[node.count] = *branch
1175		node.count++
1176		return false
1177	} else {
1178		d1splitNode(node, branch, newNode)
1179		return true
1180	}
1181}
1182
1183// Disconnect a dependent node.
1184// Caller must return (or stop using iteration index) after this as count has changed
1185func d1disconnectBranch(node *d1nodeT, index int) {
1186	// Remove element by swapping with the last element to prevent gaps in array
1187	node.branch[index] = node.branch[node.count-1]
1188	node.branch[node.count-1].data = nil
1189	node.branch[node.count-1].child = nil
1190	node.count--
1191}
1192
1193// Pick a branch.  Pick the one that will need the smallest increase
1194// in area to accomodate the new rectangle.  This will result in the
1195// least total area for the covering rectangles in the current node.
1196// In case of a tie, pick the one which was smaller before, to get
1197// the best resolution when searching.
1198func d1pickBranch(rect *d1rectT, node *d1nodeT) int {
1199	var firstTime bool = true
1200	var increase float64
1201	var bestIncr float64 = -1
1202	var area float64
1203	var bestArea float64
1204	var best int
1205	var tempRect d1rectT
1206
1207	for index := 0; index < node.count; index++ {
1208		curRect := &node.branch[index].rect
1209		area = d1calcRectVolume(curRect)
1210		tempRect = d1combineRect(rect, curRect)
1211		increase = d1calcRectVolume(&tempRect) - area
1212		if (increase < bestIncr) || firstTime {
1213			best = index
1214			bestArea = area
1215			bestIncr = increase
1216			firstTime = false
1217		} else if (increase == bestIncr) && (area < bestArea) {
1218			best = index
1219			bestArea = area
1220			bestIncr = increase
1221		}
1222	}
1223	return best
1224}
1225
1226// Combine two rectangles into larger one containing both
1227func d1combineRect(rectA, rectB *d1rectT) d1rectT {
1228	var newRect d1rectT
1229
1230	for index := 0; index < d1numDims; index++ {
1231		newRect.min[index] = d1fmin(rectA.min[index], rectB.min[index])
1232		newRect.max[index] = d1fmax(rectA.max[index], rectB.max[index])
1233	}
1234
1235	return newRect
1236}
1237
1238// Split a node.
1239// Divides the nodes branches and the extra one between two nodes.
1240// Old node is one of the new ones, and one really new one is created.
1241// Tries more than one method for choosing a partition, uses best result.
1242func d1splitNode(node *d1nodeT, branch *d1branchT, newNode **d1nodeT) {
1243	// Could just use local here, but member or external is faster since it is reused
1244	var localVars d1partitionVarsT
1245	parVars := &localVars
1246
1247	// Load all the branches into a buffer, initialize old node
1248	d1getBranches(node, branch, parVars)
1249
1250	// Find partition
1251	d1choosePartition(parVars, d1minNodes)
1252
1253	// Create a new node to hold (about) half of the branches
1254	*newNode = &d1nodeT{}
1255	(*newNode).level = node.level
1256
1257	// Put branches from buffer into 2 nodes according to the chosen partition
1258	node.count = 0
1259	d1loadNodes(node, *newNode, parVars)
1260}
1261
1262// Calculate the n-dimensional volume of a rectangle
1263func d1rectVolume(rect *d1rectT) float64 {
1264	var volume float64 = 1
1265	for index := 0; index < d1numDims; index++ {
1266		volume *= rect.max[index] - rect.min[index]
1267	}
1268	return volume
1269}
1270
1271// The exact volume of the bounding sphere for the given d1rectT
1272func d1rectSphericalVolume(rect *d1rectT) float64 {
1273	var sumOfSquares float64 = 0
1274	var radius float64
1275
1276	for index := 0; index < d1numDims; index++ {
1277		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
1278		sumOfSquares += halfExtent * halfExtent
1279	}
1280
1281	radius = math.Sqrt(sumOfSquares)
1282
1283	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
1284	if d1numDims == 5 {
1285		return (radius * radius * radius * radius * radius * d1unitSphereVolume)
1286	} else if d1numDims == 4 {
1287		return (radius * radius * radius * radius * d1unitSphereVolume)
1288	} else if d1numDims == 3 {
1289		return (radius * radius * radius * d1unitSphereVolume)
1290	} else if d1numDims == 2 {
1291		return (radius * radius * d1unitSphereVolume)
1292	} else {
1293		return (math.Pow(radius, d1numDims) * d1unitSphereVolume)
1294	}
1295}
1296
1297// Use one of the methods to calculate retangle volume
1298func d1calcRectVolume(rect *d1rectT) float64 {
1299	if d1useSphericalVolume {
1300		return d1rectSphericalVolume(rect) // Slower but helps certain merge cases
1301	} else { // RTREE_USE_SPHERICAL_VOLUME
1302		return d1rectVolume(rect) // Faster but can cause poor merges
1303	} // RTREE_USE_SPHERICAL_VOLUME
1304}
1305
1306// Load branch buffer with branches from full node plus the extra branch.
1307func d1getBranches(node *d1nodeT, branch *d1branchT, parVars *d1partitionVarsT) {
1308	// Load the branch buffer
1309	for index := 0; index < d1maxNodes; index++ {
1310		parVars.branchBuf[index] = node.branch[index]
1311	}
1312	parVars.branchBuf[d1maxNodes] = *branch
1313	parVars.branchCount = d1maxNodes + 1
1314
1315	// Calculate rect containing all in the set
1316	parVars.coverSplit = parVars.branchBuf[0].rect
1317	for index := 1; index < d1maxNodes+1; index++ {
1318		parVars.coverSplit = d1combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
1319	}
1320	parVars.coverSplitArea = d1calcRectVolume(&parVars.coverSplit)
1321}
1322
1323// Method #0 for choosing a partition:
1324// As the seeds for the two groups, pick the two rects that would waste the
1325// most area if covered by a single rectangle, i.e. evidently the worst pair
1326// to have in the same group.
1327// Of the remaining, one at a time is chosen to be put in one of the two groups.
1328// The one chosen is the one with the greatest difference in area expansion
1329// depending on which group - the rect most strongly attracted to one group
1330// and repelled from the other.
1331// If one group gets too full (more would force other group to violate min
1332// fill requirement) then other group gets the rest.
1333// These last are the ones that can go in either group most easily.
1334func d1choosePartition(parVars *d1partitionVarsT, minFill int) {
1335	var biggestDiff float64
1336	var group, chosen, betterGroup int
1337
1338	d1initParVars(parVars, parVars.branchCount, minFill)
1339	d1pickSeeds(parVars)
1340
1341	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
1342		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
1343		(parVars.count[1] < (parVars.total - parVars.minFill)) {
1344		biggestDiff = -1
1345		for index := 0; index < parVars.total; index++ {
1346			if d1notTaken == parVars.partition[index] {
1347				curRect := &parVars.branchBuf[index].rect
1348				rect0 := d1combineRect(curRect, &parVars.cover[0])
1349				rect1 := d1combineRect(curRect, &parVars.cover[1])
1350				growth0 := d1calcRectVolume(&rect0) - parVars.area[0]
1351				growth1 := d1calcRectVolume(&rect1) - parVars.area[1]
1352				diff := growth1 - growth0
1353				if diff >= 0 {
1354					group = 0
1355				} else {
1356					group = 1
1357					diff = -diff
1358				}
1359
1360				if diff > biggestDiff {
1361					biggestDiff = diff
1362					chosen = index
1363					betterGroup = group
1364				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
1365					chosen = index
1366					betterGroup = group
1367				}
1368			}
1369		}
1370		d1classify(chosen, betterGroup, parVars)
1371	}
1372
1373	// If one group too full, put remaining rects in the other
1374	if (parVars.count[0] + parVars.count[1]) < parVars.total {
1375		if parVars.count[0] >= parVars.total-parVars.minFill {
1376			group = 1
1377		} else {
1378			group = 0
1379		}
1380		for index := 0; index < parVars.total; index++ {
1381			if d1notTaken == parVars.partition[index] {
1382				d1classify(index, group, parVars)
1383			}
1384		}
1385	}
1386}
1387
1388// Copy branches from the buffer into two nodes according to the partition.
1389func d1loadNodes(nodeA, nodeB *d1nodeT, parVars *d1partitionVarsT) {
1390	for index := 0; index < parVars.total; index++ {
1391		targetNodeIndex := parVars.partition[index]
1392		targetNodes := []*d1nodeT{nodeA, nodeB}
1393
1394		// It is assured that d1addBranch here will not cause a node split.
1395		d1addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
1396	}
1397}
1398
1399// Initialize a d1partitionVarsT structure.
1400func d1initParVars(parVars *d1partitionVarsT, maxRects, minFill int) {
1401	parVars.count[0] = 0
1402	parVars.count[1] = 0
1403	parVars.area[0] = 0
1404	parVars.area[1] = 0
1405	parVars.total = maxRects
1406	parVars.minFill = minFill
1407	for index := 0; index < maxRects; index++ {
1408		parVars.partition[index] = d1notTaken
1409	}
1410}
1411
1412func d1pickSeeds(parVars *d1partitionVarsT) {
1413	var seed0, seed1 int
1414	var worst, waste float64
1415	var area [d1maxNodes + 1]float64
1416
1417	for index := 0; index < parVars.total; index++ {
1418		area[index] = d1calcRectVolume(&parVars.branchBuf[index].rect)
1419	}
1420
1421	worst = -parVars.coverSplitArea - 1
1422	for indexA := 0; indexA < parVars.total-1; indexA++ {
1423		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
1424			oneRect := d1combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
1425			waste = d1calcRectVolume(&oneRect) - area[indexA] - area[indexB]
1426			if waste > worst {
1427				worst = waste
1428				seed0 = indexA
1429				seed1 = indexB
1430			}
1431		}
1432	}
1433
1434	d1classify(seed0, 0, parVars)
1435	d1classify(seed1, 1, parVars)
1436}
1437
1438// Put a branch in one of the groups.
1439func d1classify(index, group int, parVars *d1partitionVarsT) {
1440	parVars.partition[index] = group
1441
1442	// Calculate combined rect
1443	if parVars.count[group] == 0 {
1444		parVars.cover[group] = parVars.branchBuf[index].rect
1445	} else {
1446		parVars.cover[group] = d1combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
1447	}
1448
1449	// Calculate volume of combined rect
1450	parVars.area[group] = d1calcRectVolume(&parVars.cover[group])
1451
1452	parVars.count[group]++
1453}
1454
1455// Delete a data rectangle from an index structure.
1456// Pass in a pointer to a d1rectT, the tid of the record, ptr to ptr to root node.
1457// Returns 1 if record not found, 0 if success.
1458// d1removeRect provides for eliminating the root.
1459func d1removeRect(rect *d1rectT, id interface{}, root **d1nodeT) bool {
1460	var reInsertList *d1listNodeT
1461
1462	if !d1removeRectRec(rect, id, *root, &reInsertList) {
1463		// Found and deleted a data item
1464		// Reinsert any branches from eliminated nodes
1465		for reInsertList != nil {
1466			tempNode := reInsertList.node
1467
1468			for index := 0; index < tempNode.count; index++ {
1469				// TODO go over this code. should I use (tempNode->m_level - 1)?
1470				d1insertRect(&tempNode.branch[index], root, tempNode.level)
1471			}
1472			reInsertList = reInsertList.next
1473		}
1474
1475		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
1476		// if with while? In case there is a whole branch of redundant roots...
1477		if (*root).count == 1 && (*root).isInternalNode() {
1478			tempNode := (*root).branch[0].child
1479			*root = tempNode
1480		}
1481		return false
1482	} else {
1483		return true
1484	}
1485}
1486
1487// Delete a rectangle from non-root part of an index structure.
1488// Called by d1removeRect.  Descends tree recursively,
1489// merges branches on the way back up.
1490// Returns 1 if record not found, 0 if success.
1491func d1removeRectRec(rect *d1rectT, id interface{}, node *d1nodeT, listNode **d1listNodeT) bool {
1492	if node.isInternalNode() { // not a leaf node
1493		for index := 0; index < node.count; index++ {
1494			if d1overlap(*rect, node.branch[index].rect) {
1495				if !d1removeRectRec(rect, id, node.branch[index].child, listNode) {
1496					if node.branch[index].child.count >= d1minNodes {
1497						// child removed, just resize parent rect
1498						node.branch[index].rect = d1nodeCover(node.branch[index].child)
1499					} else {
1500						// child removed, not enough entries in node, eliminate node
1501						d1reInsert(node.branch[index].child, listNode)
1502						d1disconnectBranch(node, index) // Must return after this call as count has changed
1503					}
1504					return false
1505				}
1506			}
1507		}
1508		return true
1509	} else { // A leaf node
1510		for index := 0; index < node.count; index++ {
1511			if node.branch[index].data == id {
1512				d1disconnectBranch(node, index) // Must return after this call as count has changed
1513				return false
1514			}
1515		}
1516		return true
1517	}
1518}
1519
1520// Decide whether two rectangles d1overlap.
1521func d1overlap(rectA, rectB d1rectT) bool {
1522	for index := 0; index < d1numDims; index++ {
1523		if rectA.min[index] > rectB.max[index] ||
1524			rectB.min[index] > rectA.max[index] {
1525			return false
1526		}
1527	}
1528	return true
1529}
1530
1531// Add a node to the reinsertion list.  All its branches will later
1532// be reinserted into the index structure.
1533func d1reInsert(node *d1nodeT, listNode **d1listNodeT) {
1534	newListNode := &d1listNodeT{}
1535	newListNode.node = node
1536	newListNode.next = *listNode
1537	*listNode = newListNode
1538}
1539
1540// d1search in an index tree or subtree for all data retangles that d1overlap the argument rectangle.
1541func d1search(node *d1nodeT, rect d1rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
1542	if node.isInternalNode() {
1543		// This is an internal node in the tree
1544		for index := 0; index < node.count; index++ {
1545			if d1overlap(rect, node.branch[index].rect) {
1546				var ok bool
1547				foundCount, ok = d1search(node.branch[index].child, rect, foundCount, resultCallback)
1548				if !ok {
1549					// The callback indicated to stop searching
1550					return foundCount, false
1551				}
1552			}
1553		}
1554	} else {
1555		// This is a leaf node
1556		for index := 0; index < node.count; index++ {
1557			if d1overlap(rect, node.branch[index].rect) {
1558				id := node.branch[index].data
1559				foundCount++
1560				if !resultCallback(id) {
1561					return foundCount, false // Don't continue searching
1562				}
1563
1564			}
1565		}
1566	}
1567	return foundCount, true // Continue searching
1568}
1569
1570func d2fmin(a, b float64) float64 {
1571	if a < b {
1572		return a
1573	}
1574	return b
1575}
1576func d2fmax(a, b float64) float64 {
1577	if a > b {
1578		return a
1579	}
1580	return b
1581}
1582
1583const (
1584	d2numDims            = 2
1585	d2maxNodes           = 8
1586	d2minNodes           = d2maxNodes / 2
1587	d2useSphericalVolume = true // Better split classification, may be slower on some systems
1588)
1589
1590var d2unitSphereVolume = []float64{
1591	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
1592	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
1593	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
1594	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
1595	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
1596	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
1597	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
1598}[d2numDims]
1599
1600type d2RTree struct {
1601	root *d2nodeT ///< Root of tree
1602}
1603
1604/// Minimal bounding rectangle (n-dimensional)
1605type d2rectT struct {
1606	min [d2numDims]float64 ///< Min dimensions of bounding box
1607	max [d2numDims]float64 ///< Max dimensions of bounding box
1608}
1609
1610/// May be data or may be another subtree
1611/// The parents level determines this.
1612/// If the parents level is 0, then this is data
1613type d2branchT struct {
1614	rect  d2rectT     ///< Bounds
1615	child *d2nodeT    ///< Child node
1616	data  interface{} ///< Data Id or Ptr
1617}
1618
1619/// d2nodeT for each branch level
1620type d2nodeT struct {
1621	count  int                   ///< Count
1622	level  int                   ///< Leaf is zero, others positive
1623	branch [d2maxNodes]d2branchT ///< Branch
1624}
1625
1626func (node *d2nodeT) isInternalNode() bool {
1627	return (node.level > 0) // Not a leaf, but a internal node
1628}
1629func (node *d2nodeT) isLeaf() bool {
1630	return (node.level == 0) // A leaf, contains data
1631}
1632
1633/// A link list of nodes for reinsertion after a delete operation
1634type d2listNodeT struct {
1635	next *d2listNodeT ///< Next in list
1636	node *d2nodeT     ///< Node
1637}
1638
1639const d2notTaken = -1 // indicates that position
1640
1641/// Variables for finding a split partition
1642type d2partitionVarsT struct {
1643	partition [d2maxNodes + 1]int
1644	total     int
1645	minFill   int
1646	count     [2]int
1647	cover     [2]d2rectT
1648	area      [2]float64
1649
1650	branchBuf      [d2maxNodes + 1]d2branchT
1651	branchCount    int
1652	coverSplit     d2rectT
1653	coverSplitArea float64
1654}
1655
1656func d2New() *d2RTree {
1657	// We only support machine word size simple data type eg. integer index or object pointer.
1658	// Since we are storing as union with non data branch
1659	return &d2RTree{
1660		root: &d2nodeT{},
1661	}
1662}
1663
1664/// Insert entry
1665/// \param a_min Min of bounding rect
1666/// \param a_max Max of bounding rect
1667/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
1668func (tr *d2RTree) Insert(min, max [d2numDims]float64, dataId interface{}) {
1669	var branch d2branchT
1670	branch.data = dataId
1671	for axis := 0; axis < d2numDims; axis++ {
1672		branch.rect.min[axis] = min[axis]
1673		branch.rect.max[axis] = max[axis]
1674	}
1675	d2insertRect(&branch, &tr.root, 0)
1676}
1677
1678/// Remove entry
1679/// \param a_min Min of bounding rect
1680/// \param a_max Max of bounding rect
1681/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
1682func (tr *d2RTree) Remove(min, max [d2numDims]float64, dataId interface{}) {
1683	var rect d2rectT
1684	for axis := 0; axis < d2numDims; axis++ {
1685		rect.min[axis] = min[axis]
1686		rect.max[axis] = max[axis]
1687	}
1688	d2removeRect(&rect, dataId, &tr.root)
1689}
1690
1691/// Find all within d2search rectangle
1692/// \param a_min Min of d2search bounding rect
1693/// \param a_max Max of d2search bounding rect
1694/// \param a_searchResult d2search result array.  Caller should set grow size. Function will reset, not append to array.
1695/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
1696/// \param a_context User context to pass as parameter to a_resultCallback
1697/// \return Returns the number of entries found
1698func (tr *d2RTree) Search(min, max [d2numDims]float64, resultCallback func(data interface{}) bool) int {
1699	var rect d2rectT
1700	for axis := 0; axis < d2numDims; axis++ {
1701		rect.min[axis] = min[axis]
1702		rect.max[axis] = max[axis]
1703	}
1704	foundCount, _ := d2search(tr.root, rect, 0, resultCallback)
1705	return foundCount
1706}
1707
1708/// Count the data elements in this container.  This is slow as no internal counter is maintained.
1709func (tr *d2RTree) Count() int {
1710	var count int
1711	d2countRec(tr.root, &count)
1712	return count
1713}
1714
1715/// Remove all entries from tree
1716func (tr *d2RTree) RemoveAll() {
1717	// Delete all existing nodes
1718	tr.root = &d2nodeT{}
1719}
1720
1721func d2countRec(node *d2nodeT, count *int) {
1722	if node.isInternalNode() { // not a leaf node
1723		for index := 0; index < node.count; index++ {
1724			d2countRec(node.branch[index].child, count)
1725		}
1726	} else { // A leaf node
1727		*count += node.count
1728	}
1729}
1730
1731// Inserts a new data rectangle into the index structure.
1732// Recursively descends tree, propagates splits back up.
1733// Returns 0 if node was not split.  Old node updated.
1734// If node was split, returns 1 and sets the pointer pointed to by
1735// new_node to point to the new node.  Old node updated to become one of two.
1736// The level argument specifies the number of steps up from the leaf
1737// level to insert; e.g. a data rectangle goes in at level = 0.
1738func d2insertRectRec(branch *d2branchT, node *d2nodeT, newNode **d2nodeT, level int) bool {
1739	// recurse until we reach the correct level for the new record. data records
1740	// will always be called with a_level == 0 (leaf)
1741	if node.level > level {
1742		// Still above level for insertion, go down tree recursively
1743		var otherNode *d2nodeT
1744		//var newBranch d2branchT
1745
1746		// find the optimal branch for this record
1747		index := d2pickBranch(&branch.rect, node)
1748
1749		// recursively insert this record into the picked branch
1750		childWasSplit := d2insertRectRec(branch, node.branch[index].child, &otherNode, level)
1751
1752		if !childWasSplit {
1753			// Child was not split. Merge the bounding box of the new record with the
1754			// existing bounding box
1755			node.branch[index].rect = d2combineRect(&branch.rect, &(node.branch[index].rect))
1756			return false
1757		} else {
1758			// Child was split. The old branches are now re-partitioned to two nodes
1759			// so we have to re-calculate the bounding boxes of each node
1760			node.branch[index].rect = d2nodeCover(node.branch[index].child)
1761			var newBranch d2branchT
1762			newBranch.child = otherNode
1763			newBranch.rect = d2nodeCover(otherNode)
1764
1765			// The old node is already a child of a_node. Now add the newly-created
1766			// node to a_node as well. a_node might be split because of that.
1767			return d2addBranch(&newBranch, node, newNode)
1768		}
1769	} else if node.level == level {
1770		// We have reached level for insertion. Add rect, split if necessary
1771		return d2addBranch(branch, node, newNode)
1772	} else {
1773		// Should never occur
1774		return false
1775	}
1776}
1777
1778// Insert a data rectangle into an index structure.
1779// d2insertRect provides for splitting the root;
1780// returns 1 if root was split, 0 if it was not.
1781// The level argument specifies the number of steps up from the leaf
1782// level to insert; e.g. a data rectangle goes in at level = 0.
1783// InsertRect2 does the recursion.
1784//
1785func d2insertRect(branch *d2branchT, root **d2nodeT, level int) bool {
1786	var newNode *d2nodeT
1787
1788	if d2insertRectRec(branch, *root, &newNode, level) { // Root split
1789
1790		// Grow tree taller and new root
1791		newRoot := &d2nodeT{}
1792		newRoot.level = (*root).level + 1
1793
1794		var newBranch d2branchT
1795
1796		// add old root node as a child of the new root
1797		newBranch.rect = d2nodeCover(*root)
1798		newBranch.child = *root
1799		d2addBranch(&newBranch, newRoot, nil)
1800
1801		// add the split node as a child of the new root
1802		newBranch.rect = d2nodeCover(newNode)
1803		newBranch.child = newNode
1804		d2addBranch(&newBranch, newRoot, nil)
1805
1806		// set the new root as the root node
1807		*root = newRoot
1808
1809		return true
1810	}
1811	return false
1812}
1813
1814// Find the smallest rectangle that includes all rectangles in branches of a node.
1815func d2nodeCover(node *d2nodeT) d2rectT {
1816	rect := node.branch[0].rect
1817	for index := 1; index < node.count; index++ {
1818		rect = d2combineRect(&rect, &(node.branch[index].rect))
1819	}
1820	return rect
1821}
1822
1823// Add a branch to a node.  Split the node if necessary.
1824// Returns 0 if node not split.  Old node updated.
1825// Returns 1 if node split, sets *new_node to address of new node.
1826// Old node updated, becomes one of two.
1827func d2addBranch(branch *d2branchT, node *d2nodeT, newNode **d2nodeT) bool {
1828	if node.count < d2maxNodes { // Split won't be necessary
1829		node.branch[node.count] = *branch
1830		node.count++
1831		return false
1832	} else {
1833		d2splitNode(node, branch, newNode)
1834		return true
1835	}
1836}
1837
1838// Disconnect a dependent node.
1839// Caller must return (or stop using iteration index) after this as count has changed
1840func d2disconnectBranch(node *d2nodeT, index int) {
1841	// Remove element by swapping with the last element to prevent gaps in array
1842	node.branch[index] = node.branch[node.count-1]
1843	node.branch[node.count-1].data = nil
1844	node.branch[node.count-1].child = nil
1845	node.count--
1846}
1847
1848// Pick a branch.  Pick the one that will need the smallest increase
1849// in area to accomodate the new rectangle.  This will result in the
1850// least total area for the covering rectangles in the current node.
1851// In case of a tie, pick the one which was smaller before, to get
1852// the best resolution when searching.
1853func d2pickBranch(rect *d2rectT, node *d2nodeT) int {
1854	var firstTime bool = true
1855	var increase float64
1856	var bestIncr float64 = -1
1857	var area float64
1858	var bestArea float64
1859	var best int
1860	var tempRect d2rectT
1861
1862	for index := 0; index < node.count; index++ {
1863		curRect := &node.branch[index].rect
1864		area = d2calcRectVolume(curRect)
1865		tempRect = d2combineRect(rect, curRect)
1866		increase = d2calcRectVolume(&tempRect) - area
1867		if (increase < bestIncr) || firstTime {
1868			best = index
1869			bestArea = area
1870			bestIncr = increase
1871			firstTime = false
1872		} else if (increase == bestIncr) && (area < bestArea) {
1873			best = index
1874			bestArea = area
1875			bestIncr = increase
1876		}
1877	}
1878	return best
1879}
1880
1881// Combine two rectangles into larger one containing both
1882func d2combineRect(rectA, rectB *d2rectT) d2rectT {
1883	var newRect d2rectT
1884
1885	for index := 0; index < d2numDims; index++ {
1886		newRect.min[index] = d2fmin(rectA.min[index], rectB.min[index])
1887		newRect.max[index] = d2fmax(rectA.max[index], rectB.max[index])
1888	}
1889
1890	return newRect
1891}
1892
1893// Split a node.
1894// Divides the nodes branches and the extra one between two nodes.
1895// Old node is one of the new ones, and one really new one is created.
1896// Tries more than one method for choosing a partition, uses best result.
1897func d2splitNode(node *d2nodeT, branch *d2branchT, newNode **d2nodeT) {
1898	// Could just use local here, but member or external is faster since it is reused
1899	var localVars d2partitionVarsT
1900	parVars := &localVars
1901
1902	// Load all the branches into a buffer, initialize old node
1903	d2getBranches(node, branch, parVars)
1904
1905	// Find partition
1906	d2choosePartition(parVars, d2minNodes)
1907
1908	// Create a new node to hold (about) half of the branches
1909	*newNode = &d2nodeT{}
1910	(*newNode).level = node.level
1911
1912	// Put branches from buffer into 2 nodes according to the chosen partition
1913	node.count = 0
1914	d2loadNodes(node, *newNode, parVars)
1915}
1916
1917// Calculate the n-dimensional volume of a rectangle
1918func d2rectVolume(rect *d2rectT) float64 {
1919	var volume float64 = 1
1920	for index := 0; index < d2numDims; index++ {
1921		volume *= rect.max[index] - rect.min[index]
1922	}
1923	return volume
1924}
1925
1926// The exact volume of the bounding sphere for the given d2rectT
1927func d2rectSphericalVolume(rect *d2rectT) float64 {
1928	var sumOfSquares float64 = 0
1929	var radius float64
1930
1931	for index := 0; index < d2numDims; index++ {
1932		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
1933		sumOfSquares += halfExtent * halfExtent
1934	}
1935
1936	radius = math.Sqrt(sumOfSquares)
1937
1938	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
1939	if d2numDims == 5 {
1940		return (radius * radius * radius * radius * radius * d2unitSphereVolume)
1941	} else if d2numDims == 4 {
1942		return (radius * radius * radius * radius * d2unitSphereVolume)
1943	} else if d2numDims == 3 {
1944		return (radius * radius * radius * d2unitSphereVolume)
1945	} else if d2numDims == 2 {
1946		return (radius * radius * d2unitSphereVolume)
1947	} else {
1948		return (math.Pow(radius, d2numDims) * d2unitSphereVolume)
1949	}
1950}
1951
1952// Use one of the methods to calculate retangle volume
1953func d2calcRectVolume(rect *d2rectT) float64 {
1954	if d2useSphericalVolume {
1955		return d2rectSphericalVolume(rect) // Slower but helps certain merge cases
1956	} else { // RTREE_USE_SPHERICAL_VOLUME
1957		return d2rectVolume(rect) // Faster but can cause poor merges
1958	} // RTREE_USE_SPHERICAL_VOLUME
1959}
1960
1961// Load branch buffer with branches from full node plus the extra branch.
1962func d2getBranches(node *d2nodeT, branch *d2branchT, parVars *d2partitionVarsT) {
1963	// Load the branch buffer
1964	for index := 0; index < d2maxNodes; index++ {
1965		parVars.branchBuf[index] = node.branch[index]
1966	}
1967	parVars.branchBuf[d2maxNodes] = *branch
1968	parVars.branchCount = d2maxNodes + 1
1969
1970	// Calculate rect containing all in the set
1971	parVars.coverSplit = parVars.branchBuf[0].rect
1972	for index := 1; index < d2maxNodes+1; index++ {
1973		parVars.coverSplit = d2combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
1974	}
1975	parVars.coverSplitArea = d2calcRectVolume(&parVars.coverSplit)
1976}
1977
1978// Method #0 for choosing a partition:
1979// As the seeds for the two groups, pick the two rects that would waste the
1980// most area if covered by a single rectangle, i.e. evidently the worst pair
1981// to have in the same group.
1982// Of the remaining, one at a time is chosen to be put in one of the two groups.
1983// The one chosen is the one with the greatest difference in area expansion
1984// depending on which group - the rect most strongly attracted to one group
1985// and repelled from the other.
1986// If one group gets too full (more would force other group to violate min
1987// fill requirement) then other group gets the rest.
1988// These last are the ones that can go in either group most easily.
1989func d2choosePartition(parVars *d2partitionVarsT, minFill int) {
1990	var biggestDiff float64
1991	var group, chosen, betterGroup int
1992
1993	d2initParVars(parVars, parVars.branchCount, minFill)
1994	d2pickSeeds(parVars)
1995
1996	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
1997		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
1998		(parVars.count[1] < (parVars.total - parVars.minFill)) {
1999		biggestDiff = -1
2000		for index := 0; index < parVars.total; index++ {
2001			if d2notTaken == parVars.partition[index] {
2002				curRect := &parVars.branchBuf[index].rect
2003				rect0 := d2combineRect(curRect, &parVars.cover[0])
2004				rect1 := d2combineRect(curRect, &parVars.cover[1])
2005				growth0 := d2calcRectVolume(&rect0) - parVars.area[0]
2006				growth1 := d2calcRectVolume(&rect1) - parVars.area[1]
2007				diff := growth1 - growth0
2008				if diff >= 0 {
2009					group = 0
2010				} else {
2011					group = 1
2012					diff = -diff
2013				}
2014
2015				if diff > biggestDiff {
2016					biggestDiff = diff
2017					chosen = index
2018					betterGroup = group
2019				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
2020					chosen = index
2021					betterGroup = group
2022				}
2023			}
2024		}
2025		d2classify(chosen, betterGroup, parVars)
2026	}
2027
2028	// If one group too full, put remaining rects in the other
2029	if (parVars.count[0] + parVars.count[1]) < parVars.total {
2030		if parVars.count[0] >= parVars.total-parVars.minFill {
2031			group = 1
2032		} else {
2033			group = 0
2034		}
2035		for index := 0; index < parVars.total; index++ {
2036			if d2notTaken == parVars.partition[index] {
2037				d2classify(index, group, parVars)
2038			}
2039		}
2040	}
2041}
2042
2043// Copy branches from the buffer into two nodes according to the partition.
2044func d2loadNodes(nodeA, nodeB *d2nodeT, parVars *d2partitionVarsT) {
2045	for index := 0; index < parVars.total; index++ {
2046		targetNodeIndex := parVars.partition[index]
2047		targetNodes := []*d2nodeT{nodeA, nodeB}
2048
2049		// It is assured that d2addBranch here will not cause a node split.
2050		d2addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
2051	}
2052}
2053
2054// Initialize a d2partitionVarsT structure.
2055func d2initParVars(parVars *d2partitionVarsT, maxRects, minFill int) {
2056	parVars.count[0] = 0
2057	parVars.count[1] = 0
2058	parVars.area[0] = 0
2059	parVars.area[1] = 0
2060	parVars.total = maxRects
2061	parVars.minFill = minFill
2062	for index := 0; index < maxRects; index++ {
2063		parVars.partition[index] = d2notTaken
2064	}
2065}
2066
2067func d2pickSeeds(parVars *d2partitionVarsT) {
2068	var seed0, seed1 int
2069	var worst, waste float64
2070	var area [d2maxNodes + 1]float64
2071
2072	for index := 0; index < parVars.total; index++ {
2073		area[index] = d2calcRectVolume(&parVars.branchBuf[index].rect)
2074	}
2075
2076	worst = -parVars.coverSplitArea - 1
2077	for indexA := 0; indexA < parVars.total-1; indexA++ {
2078		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
2079			oneRect := d2combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
2080			waste = d2calcRectVolume(&oneRect) - area[indexA] - area[indexB]
2081			if waste > worst {
2082				worst = waste
2083				seed0 = indexA
2084				seed1 = indexB
2085			}
2086		}
2087	}
2088
2089	d2classify(seed0, 0, parVars)
2090	d2classify(seed1, 1, parVars)
2091}
2092
2093// Put a branch in one of the groups.
2094func d2classify(index, group int, parVars *d2partitionVarsT) {
2095	parVars.partition[index] = group
2096
2097	// Calculate combined rect
2098	if parVars.count[group] == 0 {
2099		parVars.cover[group] = parVars.branchBuf[index].rect
2100	} else {
2101		parVars.cover[group] = d2combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
2102	}
2103
2104	// Calculate volume of combined rect
2105	parVars.area[group] = d2calcRectVolume(&parVars.cover[group])
2106
2107	parVars.count[group]++
2108}
2109
2110// Delete a data rectangle from an index structure.
2111// Pass in a pointer to a d2rectT, the tid of the record, ptr to ptr to root node.
2112// Returns 1 if record not found, 0 if success.
2113// d2removeRect provides for eliminating the root.
2114func d2removeRect(rect *d2rectT, id interface{}, root **d2nodeT) bool {
2115	var reInsertList *d2listNodeT
2116
2117	if !d2removeRectRec(rect, id, *root, &reInsertList) {
2118		// Found and deleted a data item
2119		// Reinsert any branches from eliminated nodes
2120		for reInsertList != nil {
2121			tempNode := reInsertList.node
2122
2123			for index := 0; index < tempNode.count; index++ {
2124				// TODO go over this code. should I use (tempNode->m_level - 1)?
2125				d2insertRect(&tempNode.branch[index], root, tempNode.level)
2126			}
2127			reInsertList = reInsertList.next
2128		}
2129
2130		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
2131		// if with while? In case there is a whole branch of redundant roots...
2132		if (*root).count == 1 && (*root).isInternalNode() {
2133			tempNode := (*root).branch[0].child
2134			*root = tempNode
2135		}
2136		return false
2137	} else {
2138		return true
2139	}
2140}
2141
2142// Delete a rectangle from non-root part of an index structure.
2143// Called by d2removeRect.  Descends tree recursively,
2144// merges branches on the way back up.
2145// Returns 1 if record not found, 0 if success.
2146func d2removeRectRec(rect *d2rectT, id interface{}, node *d2nodeT, listNode **d2listNodeT) bool {
2147	if node.isInternalNode() { // not a leaf node
2148		for index := 0; index < node.count; index++ {
2149			if d2overlap(*rect, node.branch[index].rect) {
2150				if !d2removeRectRec(rect, id, node.branch[index].child, listNode) {
2151					if node.branch[index].child.count >= d2minNodes {
2152						// child removed, just resize parent rect
2153						node.branch[index].rect = d2nodeCover(node.branch[index].child)
2154					} else {
2155						// child removed, not enough entries in node, eliminate node
2156						d2reInsert(node.branch[index].child, listNode)
2157						d2disconnectBranch(node, index) // Must return after this call as count has changed
2158					}
2159					return false
2160				}
2161			}
2162		}
2163		return true
2164	} else { // A leaf node
2165		for index := 0; index < node.count; index++ {
2166			if node.branch[index].data == id {
2167				d2disconnectBranch(node, index) // Must return after this call as count has changed
2168				return false
2169			}
2170		}
2171		return true
2172	}
2173}
2174
2175// Decide whether two rectangles d2overlap.
2176func d2overlap(rectA, rectB d2rectT) bool {
2177	for index := 0; index < d2numDims; index++ {
2178		if rectA.min[index] > rectB.max[index] ||
2179			rectB.min[index] > rectA.max[index] {
2180			return false
2181		}
2182	}
2183	return true
2184}
2185
2186// Add a node to the reinsertion list.  All its branches will later
2187// be reinserted into the index structure.
2188func d2reInsert(node *d2nodeT, listNode **d2listNodeT) {
2189	newListNode := &d2listNodeT{}
2190	newListNode.node = node
2191	newListNode.next = *listNode
2192	*listNode = newListNode
2193}
2194
2195// d2search in an index tree or subtree for all data retangles that d2overlap the argument rectangle.
2196func d2search(node *d2nodeT, rect d2rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
2197	if node.isInternalNode() {
2198		// This is an internal node in the tree
2199		for index := 0; index < node.count; index++ {
2200			if d2overlap(rect, node.branch[index].rect) {
2201				var ok bool
2202				foundCount, ok = d2search(node.branch[index].child, rect, foundCount, resultCallback)
2203				if !ok {
2204					// The callback indicated to stop searching
2205					return foundCount, false
2206				}
2207			}
2208		}
2209	} else {
2210		// This is a leaf node
2211		for index := 0; index < node.count; index++ {
2212			if d2overlap(rect, node.branch[index].rect) {
2213				id := node.branch[index].data
2214				foundCount++
2215				if !resultCallback(id) {
2216					return foundCount, false // Don't continue searching
2217				}
2218
2219			}
2220		}
2221	}
2222	return foundCount, true // Continue searching
2223}
2224
2225func d3fmin(a, b float64) float64 {
2226	if a < b {
2227		return a
2228	}
2229	return b
2230}
2231func d3fmax(a, b float64) float64 {
2232	if a > b {
2233		return a
2234	}
2235	return b
2236}
2237
2238const (
2239	d3numDims            = 3
2240	d3maxNodes           = 8
2241	d3minNodes           = d3maxNodes / 2
2242	d3useSphericalVolume = true // Better split classification, may be slower on some systems
2243)
2244
2245var d3unitSphereVolume = []float64{
2246	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
2247	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
2248	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
2249	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
2250	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
2251	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
2252	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
2253}[d3numDims]
2254
2255type d3RTree struct {
2256	root *d3nodeT ///< Root of tree
2257}
2258
2259/// Minimal bounding rectangle (n-dimensional)
2260type d3rectT struct {
2261	min [d3numDims]float64 ///< Min dimensions of bounding box
2262	max [d3numDims]float64 ///< Max dimensions of bounding box
2263}
2264
2265/// May be data or may be another subtree
2266/// The parents level determines this.
2267/// If the parents level is 0, then this is data
2268type d3branchT struct {
2269	rect  d3rectT     ///< Bounds
2270	child *d3nodeT    ///< Child node
2271	data  interface{} ///< Data Id or Ptr
2272}
2273
2274/// d3nodeT for each branch level
2275type d3nodeT struct {
2276	count  int                   ///< Count
2277	level  int                   ///< Leaf is zero, others positive
2278	branch [d3maxNodes]d3branchT ///< Branch
2279}
2280
2281func (node *d3nodeT) isInternalNode() bool {
2282	return (node.level > 0) // Not a leaf, but a internal node
2283}
2284func (node *d3nodeT) isLeaf() bool {
2285	return (node.level == 0) // A leaf, contains data
2286}
2287
2288/// A link list of nodes for reinsertion after a delete operation
2289type d3listNodeT struct {
2290	next *d3listNodeT ///< Next in list
2291	node *d3nodeT     ///< Node
2292}
2293
2294const d3notTaken = -1 // indicates that position
2295
2296/// Variables for finding a split partition
2297type d3partitionVarsT struct {
2298	partition [d3maxNodes + 1]int
2299	total     int
2300	minFill   int
2301	count     [2]int
2302	cover     [2]d3rectT
2303	area      [2]float64
2304
2305	branchBuf      [d3maxNodes + 1]d3branchT
2306	branchCount    int
2307	coverSplit     d3rectT
2308	coverSplitArea float64
2309}
2310
2311func d3New() *d3RTree {
2312	// We only support machine word size simple data type eg. integer index or object pointer.
2313	// Since we are storing as union with non data branch
2314	return &d3RTree{
2315		root: &d3nodeT{},
2316	}
2317}
2318
2319/// Insert entry
2320/// \param a_min Min of bounding rect
2321/// \param a_max Max of bounding rect
2322/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
2323func (tr *d3RTree) Insert(min, max [d3numDims]float64, dataId interface{}) {
2324	var branch d3branchT
2325	branch.data = dataId
2326	for axis := 0; axis < d3numDims; axis++ {
2327		branch.rect.min[axis] = min[axis]
2328		branch.rect.max[axis] = max[axis]
2329	}
2330	d3insertRect(&branch, &tr.root, 0)
2331}
2332
2333/// Remove entry
2334/// \param a_min Min of bounding rect
2335/// \param a_max Max of bounding rect
2336/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
2337func (tr *d3RTree) Remove(min, max [d3numDims]float64, dataId interface{}) {
2338	var rect d3rectT
2339	for axis := 0; axis < d3numDims; axis++ {
2340		rect.min[axis] = min[axis]
2341		rect.max[axis] = max[axis]
2342	}
2343	d3removeRect(&rect, dataId, &tr.root)
2344}
2345
2346/// Find all within d3search rectangle
2347/// \param a_min Min of d3search bounding rect
2348/// \param a_max Max of d3search bounding rect
2349/// \param a_searchResult d3search result array.  Caller should set grow size. Function will reset, not append to array.
2350/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
2351/// \param a_context User context to pass as parameter to a_resultCallback
2352/// \return Returns the number of entries found
2353func (tr *d3RTree) Search(min, max [d3numDims]float64, resultCallback func(data interface{}) bool) int {
2354	var rect d3rectT
2355	for axis := 0; axis < d3numDims; axis++ {
2356		rect.min[axis] = min[axis]
2357		rect.max[axis] = max[axis]
2358	}
2359	foundCount, _ := d3search(tr.root, rect, 0, resultCallback)
2360	return foundCount
2361}
2362
2363/// Count the data elements in this container.  This is slow as no internal counter is maintained.
2364func (tr *d3RTree) Count() int {
2365	var count int
2366	d3countRec(tr.root, &count)
2367	return count
2368}
2369
2370/// Remove all entries from tree
2371func (tr *d3RTree) RemoveAll() {
2372	// Delete all existing nodes
2373	tr.root = &d3nodeT{}
2374}
2375
2376func d3countRec(node *d3nodeT, count *int) {
2377	if node.isInternalNode() { // not a leaf node
2378		for index := 0; index < node.count; index++ {
2379			d3countRec(node.branch[index].child, count)
2380		}
2381	} else { // A leaf node
2382		*count += node.count
2383	}
2384}
2385
2386// Inserts a new data rectangle into the index structure.
2387// Recursively descends tree, propagates splits back up.
2388// Returns 0 if node was not split.  Old node updated.
2389// If node was split, returns 1 and sets the pointer pointed to by
2390// new_node to point to the new node.  Old node updated to become one of two.
2391// The level argument specifies the number of steps up from the leaf
2392// level to insert; e.g. a data rectangle goes in at level = 0.
2393func d3insertRectRec(branch *d3branchT, node *d3nodeT, newNode **d3nodeT, level int) bool {
2394	// recurse until we reach the correct level for the new record. data records
2395	// will always be called with a_level == 0 (leaf)
2396	if node.level > level {
2397		// Still above level for insertion, go down tree recursively
2398		var otherNode *d3nodeT
2399		//var newBranch d3branchT
2400
2401		// find the optimal branch for this record
2402		index := d3pickBranch(&branch.rect, node)
2403
2404		// recursively insert this record into the picked branch
2405		childWasSplit := d3insertRectRec(branch, node.branch[index].child, &otherNode, level)
2406
2407		if !childWasSplit {
2408			// Child was not split. Merge the bounding box of the new record with the
2409			// existing bounding box
2410			node.branch[index].rect = d3combineRect(&branch.rect, &(node.branch[index].rect))
2411			return false
2412		} else {
2413			// Child was split. The old branches are now re-partitioned to two nodes
2414			// so we have to re-calculate the bounding boxes of each node
2415			node.branch[index].rect = d3nodeCover(node.branch[index].child)
2416			var newBranch d3branchT
2417			newBranch.child = otherNode
2418			newBranch.rect = d3nodeCover(otherNode)
2419
2420			// The old node is already a child of a_node. Now add the newly-created
2421			// node to a_node as well. a_node might be split because of that.
2422			return d3addBranch(&newBranch, node, newNode)
2423		}
2424	} else if node.level == level {
2425		// We have reached level for insertion. Add rect, split if necessary
2426		return d3addBranch(branch, node, newNode)
2427	} else {
2428		// Should never occur
2429		return false
2430	}
2431}
2432
2433// Insert a data rectangle into an index structure.
2434// d3insertRect provides for splitting the root;
2435// returns 1 if root was split, 0 if it was not.
2436// The level argument specifies the number of steps up from the leaf
2437// level to insert; e.g. a data rectangle goes in at level = 0.
2438// InsertRect2 does the recursion.
2439//
2440func d3insertRect(branch *d3branchT, root **d3nodeT, level int) bool {
2441	var newNode *d3nodeT
2442
2443	if d3insertRectRec(branch, *root, &newNode, level) { // Root split
2444
2445		// Grow tree taller and new root
2446		newRoot := &d3nodeT{}
2447		newRoot.level = (*root).level + 1
2448
2449		var newBranch d3branchT
2450
2451		// add old root node as a child of the new root
2452		newBranch.rect = d3nodeCover(*root)
2453		newBranch.child = *root
2454		d3addBranch(&newBranch, newRoot, nil)
2455
2456		// add the split node as a child of the new root
2457		newBranch.rect = d3nodeCover(newNode)
2458		newBranch.child = newNode
2459		d3addBranch(&newBranch, newRoot, nil)
2460
2461		// set the new root as the root node
2462		*root = newRoot
2463
2464		return true
2465	}
2466	return false
2467}
2468
2469// Find the smallest rectangle that includes all rectangles in branches of a node.
2470func d3nodeCover(node *d3nodeT) d3rectT {
2471	rect := node.branch[0].rect
2472	for index := 1; index < node.count; index++ {
2473		rect = d3combineRect(&rect, &(node.branch[index].rect))
2474	}
2475	return rect
2476}
2477
2478// Add a branch to a node.  Split the node if necessary.
2479// Returns 0 if node not split.  Old node updated.
2480// Returns 1 if node split, sets *new_node to address of new node.
2481// Old node updated, becomes one of two.
2482func d3addBranch(branch *d3branchT, node *d3nodeT, newNode **d3nodeT) bool {
2483	if node.count < d3maxNodes { // Split won't be necessary
2484		node.branch[node.count] = *branch
2485		node.count++
2486		return false
2487	} else {
2488		d3splitNode(node, branch, newNode)
2489		return true
2490	}
2491}
2492
2493// Disconnect a dependent node.
2494// Caller must return (or stop using iteration index) after this as count has changed
2495func d3disconnectBranch(node *d3nodeT, index int) {
2496	// Remove element by swapping with the last element to prevent gaps in array
2497	node.branch[index] = node.branch[node.count-1]
2498	node.branch[node.count-1].data = nil
2499	node.branch[node.count-1].child = nil
2500	node.count--
2501}
2502
2503// Pick a branch.  Pick the one that will need the smallest increase
2504// in area to accomodate the new rectangle.  This will result in the
2505// least total area for the covering rectangles in the current node.
2506// In case of a tie, pick the one which was smaller before, to get
2507// the best resolution when searching.
2508func d3pickBranch(rect *d3rectT, node *d3nodeT) int {
2509	var firstTime bool = true
2510	var increase float64
2511	var bestIncr float64 = -1
2512	var area float64
2513	var bestArea float64
2514	var best int
2515	var tempRect d3rectT
2516
2517	for index := 0; index < node.count; index++ {
2518		curRect := &node.branch[index].rect
2519		area = d3calcRectVolume(curRect)
2520		tempRect = d3combineRect(rect, curRect)
2521		increase = d3calcRectVolume(&tempRect) - area
2522		if (increase < bestIncr) || firstTime {
2523			best = index
2524			bestArea = area
2525			bestIncr = increase
2526			firstTime = false
2527		} else if (increase == bestIncr) && (area < bestArea) {
2528			best = index
2529			bestArea = area
2530			bestIncr = increase
2531		}
2532	}
2533	return best
2534}
2535
2536// Combine two rectangles into larger one containing both
2537func d3combineRect(rectA, rectB *d3rectT) d3rectT {
2538	var newRect d3rectT
2539
2540	for index := 0; index < d3numDims; index++ {
2541		newRect.min[index] = d3fmin(rectA.min[index], rectB.min[index])
2542		newRect.max[index] = d3fmax(rectA.max[index], rectB.max[index])
2543	}
2544
2545	return newRect
2546}
2547
2548// Split a node.
2549// Divides the nodes branches and the extra one between two nodes.
2550// Old node is one of the new ones, and one really new one is created.
2551// Tries more than one method for choosing a partition, uses best result.
2552func d3splitNode(node *d3nodeT, branch *d3branchT, newNode **d3nodeT) {
2553	// Could just use local here, but member or external is faster since it is reused
2554	var localVars d3partitionVarsT
2555	parVars := &localVars
2556
2557	// Load all the branches into a buffer, initialize old node
2558	d3getBranches(node, branch, parVars)
2559
2560	// Find partition
2561	d3choosePartition(parVars, d3minNodes)
2562
2563	// Create a new node to hold (about) half of the branches
2564	*newNode = &d3nodeT{}
2565	(*newNode).level = node.level
2566
2567	// Put branches from buffer into 2 nodes according to the chosen partition
2568	node.count = 0
2569	d3loadNodes(node, *newNode, parVars)
2570}
2571
2572// Calculate the n-dimensional volume of a rectangle
2573func d3rectVolume(rect *d3rectT) float64 {
2574	var volume float64 = 1
2575	for index := 0; index < d3numDims; index++ {
2576		volume *= rect.max[index] - rect.min[index]
2577	}
2578	return volume
2579}
2580
2581// The exact volume of the bounding sphere for the given d3rectT
2582func d3rectSphericalVolume(rect *d3rectT) float64 {
2583	var sumOfSquares float64 = 0
2584	var radius float64
2585
2586	for index := 0; index < d3numDims; index++ {
2587		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
2588		sumOfSquares += halfExtent * halfExtent
2589	}
2590
2591	radius = math.Sqrt(sumOfSquares)
2592
2593	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
2594	if d3numDims == 5 {
2595		return (radius * radius * radius * radius * radius * d3unitSphereVolume)
2596	} else if d3numDims == 4 {
2597		return (radius * radius * radius * radius * d3unitSphereVolume)
2598	} else if d3numDims == 3 {
2599		return (radius * radius * radius * d3unitSphereVolume)
2600	} else if d3numDims == 2 {
2601		return (radius * radius * d3unitSphereVolume)
2602	} else {
2603		return (math.Pow(radius, d3numDims) * d3unitSphereVolume)
2604	}
2605}
2606
2607// Use one of the methods to calculate retangle volume
2608func d3calcRectVolume(rect *d3rectT) float64 {
2609	if d3useSphericalVolume {
2610		return d3rectSphericalVolume(rect) // Slower but helps certain merge cases
2611	} else { // RTREE_USE_SPHERICAL_VOLUME
2612		return d3rectVolume(rect) // Faster but can cause poor merges
2613	} // RTREE_USE_SPHERICAL_VOLUME
2614}
2615
2616// Load branch buffer with branches from full node plus the extra branch.
2617func d3getBranches(node *d3nodeT, branch *d3branchT, parVars *d3partitionVarsT) {
2618	// Load the branch buffer
2619	for index := 0; index < d3maxNodes; index++ {
2620		parVars.branchBuf[index] = node.branch[index]
2621	}
2622	parVars.branchBuf[d3maxNodes] = *branch
2623	parVars.branchCount = d3maxNodes + 1
2624
2625	// Calculate rect containing all in the set
2626	parVars.coverSplit = parVars.branchBuf[0].rect
2627	for index := 1; index < d3maxNodes+1; index++ {
2628		parVars.coverSplit = d3combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
2629	}
2630	parVars.coverSplitArea = d3calcRectVolume(&parVars.coverSplit)
2631}
2632
2633// Method #0 for choosing a partition:
2634// As the seeds for the two groups, pick the two rects that would waste the
2635// most area if covered by a single rectangle, i.e. evidently the worst pair
2636// to have in the same group.
2637// Of the remaining, one at a time is chosen to be put in one of the two groups.
2638// The one chosen is the one with the greatest difference in area expansion
2639// depending on which group - the rect most strongly attracted to one group
2640// and repelled from the other.
2641// If one group gets too full (more would force other group to violate min
2642// fill requirement) then other group gets the rest.
2643// These last are the ones that can go in either group most easily.
2644func d3choosePartition(parVars *d3partitionVarsT, minFill int) {
2645	var biggestDiff float64
2646	var group, chosen, betterGroup int
2647
2648	d3initParVars(parVars, parVars.branchCount, minFill)
2649	d3pickSeeds(parVars)
2650
2651	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
2652		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
2653		(parVars.count[1] < (parVars.total - parVars.minFill)) {
2654		biggestDiff = -1
2655		for index := 0; index < parVars.total; index++ {
2656			if d3notTaken == parVars.partition[index] {
2657				curRect := &parVars.branchBuf[index].rect
2658				rect0 := d3combineRect(curRect, &parVars.cover[0])
2659				rect1 := d3combineRect(curRect, &parVars.cover[1])
2660				growth0 := d3calcRectVolume(&rect0) - parVars.area[0]
2661				growth1 := d3calcRectVolume(&rect1) - parVars.area[1]
2662				diff := growth1 - growth0
2663				if diff >= 0 {
2664					group = 0
2665				} else {
2666					group = 1
2667					diff = -diff
2668				}
2669
2670				if diff > biggestDiff {
2671					biggestDiff = diff
2672					chosen = index
2673					betterGroup = group
2674				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
2675					chosen = index
2676					betterGroup = group
2677				}
2678			}
2679		}
2680		d3classify(chosen, betterGroup, parVars)
2681	}
2682
2683	// If one group too full, put remaining rects in the other
2684	if (parVars.count[0] + parVars.count[1]) < parVars.total {
2685		if parVars.count[0] >= parVars.total-parVars.minFill {
2686			group = 1
2687		} else {
2688			group = 0
2689		}
2690		for index := 0; index < parVars.total; index++ {
2691			if d3notTaken == parVars.partition[index] {
2692				d3classify(index, group, parVars)
2693			}
2694		}
2695	}
2696}
2697
2698// Copy branches from the buffer into two nodes according to the partition.
2699func d3loadNodes(nodeA, nodeB *d3nodeT, parVars *d3partitionVarsT) {
2700	for index := 0; index < parVars.total; index++ {
2701		targetNodeIndex := parVars.partition[index]
2702		targetNodes := []*d3nodeT{nodeA, nodeB}
2703
2704		// It is assured that d3addBranch here will not cause a node split.
2705		d3addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
2706	}
2707}
2708
2709// Initialize a d3partitionVarsT structure.
2710func d3initParVars(parVars *d3partitionVarsT, maxRects, minFill int) {
2711	parVars.count[0] = 0
2712	parVars.count[1] = 0
2713	parVars.area[0] = 0
2714	parVars.area[1] = 0
2715	parVars.total = maxRects
2716	parVars.minFill = minFill
2717	for index := 0; index < maxRects; index++ {
2718		parVars.partition[index] = d3notTaken
2719	}
2720}
2721
2722func d3pickSeeds(parVars *d3partitionVarsT) {
2723	var seed0, seed1 int
2724	var worst, waste float64
2725	var area [d3maxNodes + 1]float64
2726
2727	for index := 0; index < parVars.total; index++ {
2728		area[index] = d3calcRectVolume(&parVars.branchBuf[index].rect)
2729	}
2730
2731	worst = -parVars.coverSplitArea - 1
2732	for indexA := 0; indexA < parVars.total-1; indexA++ {
2733		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
2734			oneRect := d3combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
2735			waste = d3calcRectVolume(&oneRect) - area[indexA] - area[indexB]
2736			if waste > worst {
2737				worst = waste
2738				seed0 = indexA
2739				seed1 = indexB
2740			}
2741		}
2742	}
2743
2744	d3classify(seed0, 0, parVars)
2745	d3classify(seed1, 1, parVars)
2746}
2747
2748// Put a branch in one of the groups.
2749func d3classify(index, group int, parVars *d3partitionVarsT) {
2750	parVars.partition[index] = group
2751
2752	// Calculate combined rect
2753	if parVars.count[group] == 0 {
2754		parVars.cover[group] = parVars.branchBuf[index].rect
2755	} else {
2756		parVars.cover[group] = d3combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
2757	}
2758
2759	// Calculate volume of combined rect
2760	parVars.area[group] = d3calcRectVolume(&parVars.cover[group])
2761
2762	parVars.count[group]++
2763}
2764
2765// Delete a data rectangle from an index structure.
2766// Pass in a pointer to a d3rectT, the tid of the record, ptr to ptr to root node.
2767// Returns 1 if record not found, 0 if success.
2768// d3removeRect provides for eliminating the root.
2769func d3removeRect(rect *d3rectT, id interface{}, root **d3nodeT) bool {
2770	var reInsertList *d3listNodeT
2771
2772	if !d3removeRectRec(rect, id, *root, &reInsertList) {
2773		// Found and deleted a data item
2774		// Reinsert any branches from eliminated nodes
2775		for reInsertList != nil {
2776			tempNode := reInsertList.node
2777
2778			for index := 0; index < tempNode.count; index++ {
2779				// TODO go over this code. should I use (tempNode->m_level - 1)?
2780				d3insertRect(&tempNode.branch[index], root, tempNode.level)
2781			}
2782			reInsertList = reInsertList.next
2783		}
2784
2785		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
2786		// if with while? In case there is a whole branch of redundant roots...
2787		if (*root).count == 1 && (*root).isInternalNode() {
2788			tempNode := (*root).branch[0].child
2789			*root = tempNode
2790		}
2791		return false
2792	} else {
2793		return true
2794	}
2795}
2796
2797// Delete a rectangle from non-root part of an index structure.
2798// Called by d3removeRect.  Descends tree recursively,
2799// merges branches on the way back up.
2800// Returns 1 if record not found, 0 if success.
2801func d3removeRectRec(rect *d3rectT, id interface{}, node *d3nodeT, listNode **d3listNodeT) bool {
2802	if node.isInternalNode() { // not a leaf node
2803		for index := 0; index < node.count; index++ {
2804			if d3overlap(*rect, node.branch[index].rect) {
2805				if !d3removeRectRec(rect, id, node.branch[index].child, listNode) {
2806					if node.branch[index].child.count >= d3minNodes {
2807						// child removed, just resize parent rect
2808						node.branch[index].rect = d3nodeCover(node.branch[index].child)
2809					} else {
2810						// child removed, not enough entries in node, eliminate node
2811						d3reInsert(node.branch[index].child, listNode)
2812						d3disconnectBranch(node, index) // Must return after this call as count has changed
2813					}
2814					return false
2815				}
2816			}
2817		}
2818		return true
2819	} else { // A leaf node
2820		for index := 0; index < node.count; index++ {
2821			if node.branch[index].data == id {
2822				d3disconnectBranch(node, index) // Must return after this call as count has changed
2823				return false
2824			}
2825		}
2826		return true
2827	}
2828}
2829
2830// Decide whether two rectangles d3overlap.
2831func d3overlap(rectA, rectB d3rectT) bool {
2832	for index := 0; index < d3numDims; index++ {
2833		if rectA.min[index] > rectB.max[index] ||
2834			rectB.min[index] > rectA.max[index] {
2835			return false
2836		}
2837	}
2838	return true
2839}
2840
2841// Add a node to the reinsertion list.  All its branches will later
2842// be reinserted into the index structure.
2843func d3reInsert(node *d3nodeT, listNode **d3listNodeT) {
2844	newListNode := &d3listNodeT{}
2845	newListNode.node = node
2846	newListNode.next = *listNode
2847	*listNode = newListNode
2848}
2849
2850// d3search in an index tree or subtree for all data retangles that d3overlap the argument rectangle.
2851func d3search(node *d3nodeT, rect d3rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
2852	if node.isInternalNode() {
2853		// This is an internal node in the tree
2854		for index := 0; index < node.count; index++ {
2855			if d3overlap(rect, node.branch[index].rect) {
2856				var ok bool
2857				foundCount, ok = d3search(node.branch[index].child, rect, foundCount, resultCallback)
2858				if !ok {
2859					// The callback indicated to stop searching
2860					return foundCount, false
2861				}
2862			}
2863		}
2864	} else {
2865		// This is a leaf node
2866		for index := 0; index < node.count; index++ {
2867			if d3overlap(rect, node.branch[index].rect) {
2868				id := node.branch[index].data
2869				foundCount++
2870				if !resultCallback(id) {
2871					return foundCount, false // Don't continue searching
2872				}
2873
2874			}
2875		}
2876	}
2877	return foundCount, true // Continue searching
2878}
2879
2880func d4fmin(a, b float64) float64 {
2881	if a < b {
2882		return a
2883	}
2884	return b
2885}
2886func d4fmax(a, b float64) float64 {
2887	if a > b {
2888		return a
2889	}
2890	return b
2891}
2892
2893const (
2894	d4numDims            = 4
2895	d4maxNodes           = 8
2896	d4minNodes           = d4maxNodes / 2
2897	d4useSphericalVolume = true // Better split classification, may be slower on some systems
2898)
2899
2900var d4unitSphereVolume = []float64{
2901	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
2902	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
2903	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
2904	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
2905	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
2906	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
2907	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
2908}[d4numDims]
2909
2910type d4RTree struct {
2911	root *d4nodeT ///< Root of tree
2912}
2913
2914/// Minimal bounding rectangle (n-dimensional)
2915type d4rectT struct {
2916	min [d4numDims]float64 ///< Min dimensions of bounding box
2917	max [d4numDims]float64 ///< Max dimensions of bounding box
2918}
2919
2920/// May be data or may be another subtree
2921/// The parents level determines this.
2922/// If the parents level is 0, then this is data
2923type d4branchT struct {
2924	rect  d4rectT     ///< Bounds
2925	child *d4nodeT    ///< Child node
2926	data  interface{} ///< Data Id or Ptr
2927}
2928
2929/// d4nodeT for each branch level
2930type d4nodeT struct {
2931	count  int                   ///< Count
2932	level  int                   ///< Leaf is zero, others positive
2933	branch [d4maxNodes]d4branchT ///< Branch
2934}
2935
2936func (node *d4nodeT) isInternalNode() bool {
2937	return (node.level > 0) // Not a leaf, but a internal node
2938}
2939func (node *d4nodeT) isLeaf() bool {
2940	return (node.level == 0) // A leaf, contains data
2941}
2942
2943/// A link list of nodes for reinsertion after a delete operation
2944type d4listNodeT struct {
2945	next *d4listNodeT ///< Next in list
2946	node *d4nodeT     ///< Node
2947}
2948
2949const d4notTaken = -1 // indicates that position
2950
2951/// Variables for finding a split partition
2952type d4partitionVarsT struct {
2953	partition [d4maxNodes + 1]int
2954	total     int
2955	minFill   int
2956	count     [2]int
2957	cover     [2]d4rectT
2958	area      [2]float64
2959
2960	branchBuf      [d4maxNodes + 1]d4branchT
2961	branchCount    int
2962	coverSplit     d4rectT
2963	coverSplitArea float64
2964}
2965
2966func d4New() *d4RTree {
2967	// We only support machine word size simple data type eg. integer index or object pointer.
2968	// Since we are storing as union with non data branch
2969	return &d4RTree{
2970		root: &d4nodeT{},
2971	}
2972}
2973
2974/// Insert entry
2975/// \param a_min Min of bounding rect
2976/// \param a_max Max of bounding rect
2977/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
2978func (tr *d4RTree) Insert(min, max [d4numDims]float64, dataId interface{}) {
2979	var branch d4branchT
2980	branch.data = dataId
2981	for axis := 0; axis < d4numDims; axis++ {
2982		branch.rect.min[axis] = min[axis]
2983		branch.rect.max[axis] = max[axis]
2984	}
2985	d4insertRect(&branch, &tr.root, 0)
2986}
2987
2988/// Remove entry
2989/// \param a_min Min of bounding rect
2990/// \param a_max Max of bounding rect
2991/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
2992func (tr *d4RTree) Remove(min, max [d4numDims]float64, dataId interface{}) {
2993	var rect d4rectT
2994	for axis := 0; axis < d4numDims; axis++ {
2995		rect.min[axis] = min[axis]
2996		rect.max[axis] = max[axis]
2997	}
2998	d4removeRect(&rect, dataId, &tr.root)
2999}
3000
3001/// Find all within d4search rectangle
3002/// \param a_min Min of d4search bounding rect
3003/// \param a_max Max of d4search bounding rect
3004/// \param a_searchResult d4search result array.  Caller should set grow size. Function will reset, not append to array.
3005/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
3006/// \param a_context User context to pass as parameter to a_resultCallback
3007/// \return Returns the number of entries found
3008func (tr *d4RTree) Search(min, max [d4numDims]float64, resultCallback func(data interface{}) bool) int {
3009	var rect d4rectT
3010	for axis := 0; axis < d4numDims; axis++ {
3011		rect.min[axis] = min[axis]
3012		rect.max[axis] = max[axis]
3013	}
3014	foundCount, _ := d4search(tr.root, rect, 0, resultCallback)
3015	return foundCount
3016}
3017
3018/// Count the data elements in this container.  This is slow as no internal counter is maintained.
3019func (tr *d4RTree) Count() int {
3020	var count int
3021	d4countRec(tr.root, &count)
3022	return count
3023}
3024
3025/// Remove all entries from tree
3026func (tr *d4RTree) RemoveAll() {
3027	// Delete all existing nodes
3028	tr.root = &d4nodeT{}
3029}
3030
3031func d4countRec(node *d4nodeT, count *int) {
3032	if node.isInternalNode() { // not a leaf node
3033		for index := 0; index < node.count; index++ {
3034			d4countRec(node.branch[index].child, count)
3035		}
3036	} else { // A leaf node
3037		*count += node.count
3038	}
3039}
3040
3041// Inserts a new data rectangle into the index structure.
3042// Recursively descends tree, propagates splits back up.
3043// Returns 0 if node was not split.  Old node updated.
3044// If node was split, returns 1 and sets the pointer pointed to by
3045// new_node to point to the new node.  Old node updated to become one of two.
3046// The level argument specifies the number of steps up from the leaf
3047// level to insert; e.g. a data rectangle goes in at level = 0.
3048func d4insertRectRec(branch *d4branchT, node *d4nodeT, newNode **d4nodeT, level int) bool {
3049	// recurse until we reach the correct level for the new record. data records
3050	// will always be called with a_level == 0 (leaf)
3051	if node.level > level {
3052		// Still above level for insertion, go down tree recursively
3053		var otherNode *d4nodeT
3054		//var newBranch d4branchT
3055
3056		// find the optimal branch for this record
3057		index := d4pickBranch(&branch.rect, node)
3058
3059		// recursively insert this record into the picked branch
3060		childWasSplit := d4insertRectRec(branch, node.branch[index].child, &otherNode, level)
3061
3062		if !childWasSplit {
3063			// Child was not split. Merge the bounding box of the new record with the
3064			// existing bounding box
3065			node.branch[index].rect = d4combineRect(&branch.rect, &(node.branch[index].rect))
3066			return false
3067		} else {
3068			// Child was split. The old branches are now re-partitioned to two nodes
3069			// so we have to re-calculate the bounding boxes of each node
3070			node.branch[index].rect = d4nodeCover(node.branch[index].child)
3071			var newBranch d4branchT
3072			newBranch.child = otherNode
3073			newBranch.rect = d4nodeCover(otherNode)
3074
3075			// The old node is already a child of a_node. Now add the newly-created
3076			// node to a_node as well. a_node might be split because of that.
3077			return d4addBranch(&newBranch, node, newNode)
3078		}
3079	} else if node.level == level {
3080		// We have reached level for insertion. Add rect, split if necessary
3081		return d4addBranch(branch, node, newNode)
3082	} else {
3083		// Should never occur
3084		return false
3085	}
3086}
3087
3088// Insert a data rectangle into an index structure.
3089// d4insertRect provides for splitting the root;
3090// returns 1 if root was split, 0 if it was not.
3091// The level argument specifies the number of steps up from the leaf
3092// level to insert; e.g. a data rectangle goes in at level = 0.
3093// InsertRect2 does the recursion.
3094//
3095func d4insertRect(branch *d4branchT, root **d4nodeT, level int) bool {
3096	var newNode *d4nodeT
3097
3098	if d4insertRectRec(branch, *root, &newNode, level) { // Root split
3099
3100		// Grow tree taller and new root
3101		newRoot := &d4nodeT{}
3102		newRoot.level = (*root).level + 1
3103
3104		var newBranch d4branchT
3105
3106		// add old root node as a child of the new root
3107		newBranch.rect = d4nodeCover(*root)
3108		newBranch.child = *root
3109		d4addBranch(&newBranch, newRoot, nil)
3110
3111		// add the split node as a child of the new root
3112		newBranch.rect = d4nodeCover(newNode)
3113		newBranch.child = newNode
3114		d4addBranch(&newBranch, newRoot, nil)
3115
3116		// set the new root as the root node
3117		*root = newRoot
3118
3119		return true
3120	}
3121	return false
3122}
3123
3124// Find the smallest rectangle that includes all rectangles in branches of a node.
3125func d4nodeCover(node *d4nodeT) d4rectT {
3126	rect := node.branch[0].rect
3127	for index := 1; index < node.count; index++ {
3128		rect = d4combineRect(&rect, &(node.branch[index].rect))
3129	}
3130	return rect
3131}
3132
3133// Add a branch to a node.  Split the node if necessary.
3134// Returns 0 if node not split.  Old node updated.
3135// Returns 1 if node split, sets *new_node to address of new node.
3136// Old node updated, becomes one of two.
3137func d4addBranch(branch *d4branchT, node *d4nodeT, newNode **d4nodeT) bool {
3138	if node.count < d4maxNodes { // Split won't be necessary
3139		node.branch[node.count] = *branch
3140		node.count++
3141		return false
3142	} else {
3143		d4splitNode(node, branch, newNode)
3144		return true
3145	}
3146}
3147
3148// Disconnect a dependent node.
3149// Caller must return (or stop using iteration index) after this as count has changed
3150func d4disconnectBranch(node *d4nodeT, index int) {
3151	// Remove element by swapping with the last element to prevent gaps in array
3152	node.branch[index] = node.branch[node.count-1]
3153	node.branch[node.count-1].data = nil
3154	node.branch[node.count-1].child = nil
3155	node.count--
3156}
3157
3158// Pick a branch.  Pick the one that will need the smallest increase
3159// in area to accomodate the new rectangle.  This will result in the
3160// least total area for the covering rectangles in the current node.
3161// In case of a tie, pick the one which was smaller before, to get
3162// the best resolution when searching.
3163func d4pickBranch(rect *d4rectT, node *d4nodeT) int {
3164	var firstTime bool = true
3165	var increase float64
3166	var bestIncr float64 = -1
3167	var area float64
3168	var bestArea float64
3169	var best int
3170	var tempRect d4rectT
3171
3172	for index := 0; index < node.count; index++ {
3173		curRect := &node.branch[index].rect
3174		area = d4calcRectVolume(curRect)
3175		tempRect = d4combineRect(rect, curRect)
3176		increase = d4calcRectVolume(&tempRect) - area
3177		if (increase < bestIncr) || firstTime {
3178			best = index
3179			bestArea = area
3180			bestIncr = increase
3181			firstTime = false
3182		} else if (increase == bestIncr) && (area < bestArea) {
3183			best = index
3184			bestArea = area
3185			bestIncr = increase
3186		}
3187	}
3188	return best
3189}
3190
3191// Combine two rectangles into larger one containing both
3192func d4combineRect(rectA, rectB *d4rectT) d4rectT {
3193	var newRect d4rectT
3194
3195	for index := 0; index < d4numDims; index++ {
3196		newRect.min[index] = d4fmin(rectA.min[index], rectB.min[index])
3197		newRect.max[index] = d4fmax(rectA.max[index], rectB.max[index])
3198	}
3199
3200	return newRect
3201}
3202
3203// Split a node.
3204// Divides the nodes branches and the extra one between two nodes.
3205// Old node is one of the new ones, and one really new one is created.
3206// Tries more than one method for choosing a partition, uses best result.
3207func d4splitNode(node *d4nodeT, branch *d4branchT, newNode **d4nodeT) {
3208	// Could just use local here, but member or external is faster since it is reused
3209	var localVars d4partitionVarsT
3210	parVars := &localVars
3211
3212	// Load all the branches into a buffer, initialize old node
3213	d4getBranches(node, branch, parVars)
3214
3215	// Find partition
3216	d4choosePartition(parVars, d4minNodes)
3217
3218	// Create a new node to hold (about) half of the branches
3219	*newNode = &d4nodeT{}
3220	(*newNode).level = node.level
3221
3222	// Put branches from buffer into 2 nodes according to the chosen partition
3223	node.count = 0
3224	d4loadNodes(node, *newNode, parVars)
3225}
3226
3227// Calculate the n-dimensional volume of a rectangle
3228func d4rectVolume(rect *d4rectT) float64 {
3229	var volume float64 = 1
3230	for index := 0; index < d4numDims; index++ {
3231		volume *= rect.max[index] - rect.min[index]
3232	}
3233	return volume
3234}
3235
3236// The exact volume of the bounding sphere for the given d4rectT
3237func d4rectSphericalVolume(rect *d4rectT) float64 {
3238	var sumOfSquares float64 = 0
3239	var radius float64
3240
3241	for index := 0; index < d4numDims; index++ {
3242		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
3243		sumOfSquares += halfExtent * halfExtent
3244	}
3245
3246	radius = math.Sqrt(sumOfSquares)
3247
3248	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
3249	if d4numDims == 5 {
3250		return (radius * radius * radius * radius * radius * d4unitSphereVolume)
3251	} else if d4numDims == 4 {
3252		return (radius * radius * radius * radius * d4unitSphereVolume)
3253	} else if d4numDims == 3 {
3254		return (radius * radius * radius * d4unitSphereVolume)
3255	} else if d4numDims == 2 {
3256		return (radius * radius * d4unitSphereVolume)
3257	} else {
3258		return (math.Pow(radius, d4numDims) * d4unitSphereVolume)
3259	}
3260}
3261
3262// Use one of the methods to calculate retangle volume
3263func d4calcRectVolume(rect *d4rectT) float64 {
3264	if d4useSphericalVolume {
3265		return d4rectSphericalVolume(rect) // Slower but helps certain merge cases
3266	} else { // RTREE_USE_SPHERICAL_VOLUME
3267		return d4rectVolume(rect) // Faster but can cause poor merges
3268	} // RTREE_USE_SPHERICAL_VOLUME
3269}
3270
3271// Load branch buffer with branches from full node plus the extra branch.
3272func d4getBranches(node *d4nodeT, branch *d4branchT, parVars *d4partitionVarsT) {
3273	// Load the branch buffer
3274	for index := 0; index < d4maxNodes; index++ {
3275		parVars.branchBuf[index] = node.branch[index]
3276	}
3277	parVars.branchBuf[d4maxNodes] = *branch
3278	parVars.branchCount = d4maxNodes + 1
3279
3280	// Calculate rect containing all in the set
3281	parVars.coverSplit = parVars.branchBuf[0].rect
3282	for index := 1; index < d4maxNodes+1; index++ {
3283		parVars.coverSplit = d4combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
3284	}
3285	parVars.coverSplitArea = d4calcRectVolume(&parVars.coverSplit)
3286}
3287
3288// Method #0 for choosing a partition:
3289// As the seeds for the two groups, pick the two rects that would waste the
3290// most area if covered by a single rectangle, i.e. evidently the worst pair
3291// to have in the same group.
3292// Of the remaining, one at a time is chosen to be put in one of the two groups.
3293// The one chosen is the one with the greatest difference in area expansion
3294// depending on which group - the rect most strongly attracted to one group
3295// and repelled from the other.
3296// If one group gets too full (more would force other group to violate min
3297// fill requirement) then other group gets the rest.
3298// These last are the ones that can go in either group most easily.
3299func d4choosePartition(parVars *d4partitionVarsT, minFill int) {
3300	var biggestDiff float64
3301	var group, chosen, betterGroup int
3302
3303	d4initParVars(parVars, parVars.branchCount, minFill)
3304	d4pickSeeds(parVars)
3305
3306	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
3307		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
3308		(parVars.count[1] < (parVars.total - parVars.minFill)) {
3309		biggestDiff = -1
3310		for index := 0; index < parVars.total; index++ {
3311			if d4notTaken == parVars.partition[index] {
3312				curRect := &parVars.branchBuf[index].rect
3313				rect0 := d4combineRect(curRect, &parVars.cover[0])
3314				rect1 := d4combineRect(curRect, &parVars.cover[1])
3315				growth0 := d4calcRectVolume(&rect0) - parVars.area[0]
3316				growth1 := d4calcRectVolume(&rect1) - parVars.area[1]
3317				diff := growth1 - growth0
3318				if diff >= 0 {
3319					group = 0
3320				} else {
3321					group = 1
3322					diff = -diff
3323				}
3324
3325				if diff > biggestDiff {
3326					biggestDiff = diff
3327					chosen = index
3328					betterGroup = group
3329				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
3330					chosen = index
3331					betterGroup = group
3332				}
3333			}
3334		}
3335		d4classify(chosen, betterGroup, parVars)
3336	}
3337
3338	// If one group too full, put remaining rects in the other
3339	if (parVars.count[0] + parVars.count[1]) < parVars.total {
3340		if parVars.count[0] >= parVars.total-parVars.minFill {
3341			group = 1
3342		} else {
3343			group = 0
3344		}
3345		for index := 0; index < parVars.total; index++ {
3346			if d4notTaken == parVars.partition[index] {
3347				d4classify(index, group, parVars)
3348			}
3349		}
3350	}
3351}
3352
3353// Copy branches from the buffer into two nodes according to the partition.
3354func d4loadNodes(nodeA, nodeB *d4nodeT, parVars *d4partitionVarsT) {
3355	for index := 0; index < parVars.total; index++ {
3356		targetNodeIndex := parVars.partition[index]
3357		targetNodes := []*d4nodeT{nodeA, nodeB}
3358
3359		// It is assured that d4addBranch here will not cause a node split.
3360		d4addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
3361	}
3362}
3363
3364// Initialize a d4partitionVarsT structure.
3365func d4initParVars(parVars *d4partitionVarsT, maxRects, minFill int) {
3366	parVars.count[0] = 0
3367	parVars.count[1] = 0
3368	parVars.area[0] = 0
3369	parVars.area[1] = 0
3370	parVars.total = maxRects
3371	parVars.minFill = minFill
3372	for index := 0; index < maxRects; index++ {
3373		parVars.partition[index] = d4notTaken
3374	}
3375}
3376
3377func d4pickSeeds(parVars *d4partitionVarsT) {
3378	var seed0, seed1 int
3379	var worst, waste float64
3380	var area [d4maxNodes + 1]float64
3381
3382	for index := 0; index < parVars.total; index++ {
3383		area[index] = d4calcRectVolume(&parVars.branchBuf[index].rect)
3384	}
3385
3386	worst = -parVars.coverSplitArea - 1
3387	for indexA := 0; indexA < parVars.total-1; indexA++ {
3388		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
3389			oneRect := d4combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
3390			waste = d4calcRectVolume(&oneRect) - area[indexA] - area[indexB]
3391			if waste > worst {
3392				worst = waste
3393				seed0 = indexA
3394				seed1 = indexB
3395			}
3396		}
3397	}
3398
3399	d4classify(seed0, 0, parVars)
3400	d4classify(seed1, 1, parVars)
3401}
3402
3403// Put a branch in one of the groups.
3404func d4classify(index, group int, parVars *d4partitionVarsT) {
3405	parVars.partition[index] = group
3406
3407	// Calculate combined rect
3408	if parVars.count[group] == 0 {
3409		parVars.cover[group] = parVars.branchBuf[index].rect
3410	} else {
3411		parVars.cover[group] = d4combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
3412	}
3413
3414	// Calculate volume of combined rect
3415	parVars.area[group] = d4calcRectVolume(&parVars.cover[group])
3416
3417	parVars.count[group]++
3418}
3419
3420// Delete a data rectangle from an index structure.
3421// Pass in a pointer to a d4rectT, the tid of the record, ptr to ptr to root node.
3422// Returns 1 if record not found, 0 if success.
3423// d4removeRect provides for eliminating the root.
3424func d4removeRect(rect *d4rectT, id interface{}, root **d4nodeT) bool {
3425	var reInsertList *d4listNodeT
3426
3427	if !d4removeRectRec(rect, id, *root, &reInsertList) {
3428		// Found and deleted a data item
3429		// Reinsert any branches from eliminated nodes
3430		for reInsertList != nil {
3431			tempNode := reInsertList.node
3432
3433			for index := 0; index < tempNode.count; index++ {
3434				// TODO go over this code. should I use (tempNode->m_level - 1)?
3435				d4insertRect(&tempNode.branch[index], root, tempNode.level)
3436			}
3437			reInsertList = reInsertList.next
3438		}
3439
3440		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
3441		// if with while? In case there is a whole branch of redundant roots...
3442		if (*root).count == 1 && (*root).isInternalNode() {
3443			tempNode := (*root).branch[0].child
3444			*root = tempNode
3445		}
3446		return false
3447	} else {
3448		return true
3449	}
3450}
3451
3452// Delete a rectangle from non-root part of an index structure.
3453// Called by d4removeRect.  Descends tree recursively,
3454// merges branches on the way back up.
3455// Returns 1 if record not found, 0 if success.
3456func d4removeRectRec(rect *d4rectT, id interface{}, node *d4nodeT, listNode **d4listNodeT) bool {
3457	if node.isInternalNode() { // not a leaf node
3458		for index := 0; index < node.count; index++ {
3459			if d4overlap(*rect, node.branch[index].rect) {
3460				if !d4removeRectRec(rect, id, node.branch[index].child, listNode) {
3461					if node.branch[index].child.count >= d4minNodes {
3462						// child removed, just resize parent rect
3463						node.branch[index].rect = d4nodeCover(node.branch[index].child)
3464					} else {
3465						// child removed, not enough entries in node, eliminate node
3466						d4reInsert(node.branch[index].child, listNode)
3467						d4disconnectBranch(node, index) // Must return after this call as count has changed
3468					}
3469					return false
3470				}
3471			}
3472		}
3473		return true
3474	} else { // A leaf node
3475		for index := 0; index < node.count; index++ {
3476			if node.branch[index].data == id {
3477				d4disconnectBranch(node, index) // Must return after this call as count has changed
3478				return false
3479			}
3480		}
3481		return true
3482	}
3483}
3484
3485// Decide whether two rectangles d4overlap.
3486func d4overlap(rectA, rectB d4rectT) bool {
3487	for index := 0; index < d4numDims; index++ {
3488		if rectA.min[index] > rectB.max[index] ||
3489			rectB.min[index] > rectA.max[index] {
3490			return false
3491		}
3492	}
3493	return true
3494}
3495
3496// Add a node to the reinsertion list.  All its branches will later
3497// be reinserted into the index structure.
3498func d4reInsert(node *d4nodeT, listNode **d4listNodeT) {
3499	newListNode := &d4listNodeT{}
3500	newListNode.node = node
3501	newListNode.next = *listNode
3502	*listNode = newListNode
3503}
3504
3505// d4search in an index tree or subtree for all data retangles that d4overlap the argument rectangle.
3506func d4search(node *d4nodeT, rect d4rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
3507	if node.isInternalNode() {
3508		// This is an internal node in the tree
3509		for index := 0; index < node.count; index++ {
3510			if d4overlap(rect, node.branch[index].rect) {
3511				var ok bool
3512				foundCount, ok = d4search(node.branch[index].child, rect, foundCount, resultCallback)
3513				if !ok {
3514					// The callback indicated to stop searching
3515					return foundCount, false
3516				}
3517			}
3518		}
3519	} else {
3520		// This is a leaf node
3521		for index := 0; index < node.count; index++ {
3522			if d4overlap(rect, node.branch[index].rect) {
3523				id := node.branch[index].data
3524				foundCount++
3525				if !resultCallback(id) {
3526					return foundCount, false // Don't continue searching
3527				}
3528
3529			}
3530		}
3531	}
3532	return foundCount, true // Continue searching
3533}
3534
3535func d5fmin(a, b float64) float64 {
3536	if a < b {
3537		return a
3538	}
3539	return b
3540}
3541func d5fmax(a, b float64) float64 {
3542	if a > b {
3543		return a
3544	}
3545	return b
3546}
3547
3548const (
3549	d5numDims            = 5
3550	d5maxNodes           = 8
3551	d5minNodes           = d5maxNodes / 2
3552	d5useSphericalVolume = true // Better split classification, may be slower on some systems
3553)
3554
3555var d5unitSphereVolume = []float64{
3556	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
3557	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
3558	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
3559	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
3560	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
3561	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
3562	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
3563}[d5numDims]
3564
3565type d5RTree struct {
3566	root *d5nodeT ///< Root of tree
3567}
3568
3569/// Minimal bounding rectangle (n-dimensional)
3570type d5rectT struct {
3571	min [d5numDims]float64 ///< Min dimensions of bounding box
3572	max [d5numDims]float64 ///< Max dimensions of bounding box
3573}
3574
3575/// May be data or may be another subtree
3576/// The parents level determines this.
3577/// If the parents level is 0, then this is data
3578type d5branchT struct {
3579	rect  d5rectT     ///< Bounds
3580	child *d5nodeT    ///< Child node
3581	data  interface{} ///< Data Id or Ptr
3582}
3583
3584/// d5nodeT for each branch level
3585type d5nodeT struct {
3586	count  int                   ///< Count
3587	level  int                   ///< Leaf is zero, others positive
3588	branch [d5maxNodes]d5branchT ///< Branch
3589}
3590
3591func (node *d5nodeT) isInternalNode() bool {
3592	return (node.level > 0) // Not a leaf, but a internal node
3593}
3594func (node *d5nodeT) isLeaf() bool {
3595	return (node.level == 0) // A leaf, contains data
3596}
3597
3598/// A link list of nodes for reinsertion after a delete operation
3599type d5listNodeT struct {
3600	next *d5listNodeT ///< Next in list
3601	node *d5nodeT     ///< Node
3602}
3603
3604const d5notTaken = -1 // indicates that position
3605
3606/// Variables for finding a split partition
3607type d5partitionVarsT struct {
3608	partition [d5maxNodes + 1]int
3609	total     int
3610	minFill   int
3611	count     [2]int
3612	cover     [2]d5rectT
3613	area      [2]float64
3614
3615	branchBuf      [d5maxNodes + 1]d5branchT
3616	branchCount    int
3617	coverSplit     d5rectT
3618	coverSplitArea float64
3619}
3620
3621func d5New() *d5RTree {
3622	// We only support machine word size simple data type eg. integer index or object pointer.
3623	// Since we are storing as union with non data branch
3624	return &d5RTree{
3625		root: &d5nodeT{},
3626	}
3627}
3628
3629/// Insert entry
3630/// \param a_min Min of bounding rect
3631/// \param a_max Max of bounding rect
3632/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
3633func (tr *d5RTree) Insert(min, max [d5numDims]float64, dataId interface{}) {
3634	var branch d5branchT
3635	branch.data = dataId
3636	for axis := 0; axis < d5numDims; axis++ {
3637		branch.rect.min[axis] = min[axis]
3638		branch.rect.max[axis] = max[axis]
3639	}
3640	d5insertRect(&branch, &tr.root, 0)
3641}
3642
3643/// Remove entry
3644/// \param a_min Min of bounding rect
3645/// \param a_max Max of bounding rect
3646/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
3647func (tr *d5RTree) Remove(min, max [d5numDims]float64, dataId interface{}) {
3648	var rect d5rectT
3649	for axis := 0; axis < d5numDims; axis++ {
3650		rect.min[axis] = min[axis]
3651		rect.max[axis] = max[axis]
3652	}
3653	d5removeRect(&rect, dataId, &tr.root)
3654}
3655
3656/// Find all within d5search rectangle
3657/// \param a_min Min of d5search bounding rect
3658/// \param a_max Max of d5search bounding rect
3659/// \param a_searchResult d5search result array.  Caller should set grow size. Function will reset, not append to array.
3660/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
3661/// \param a_context User context to pass as parameter to a_resultCallback
3662/// \return Returns the number of entries found
3663func (tr *d5RTree) Search(min, max [d5numDims]float64, resultCallback func(data interface{}) bool) int {
3664	var rect d5rectT
3665	for axis := 0; axis < d5numDims; axis++ {
3666		rect.min[axis] = min[axis]
3667		rect.max[axis] = max[axis]
3668	}
3669	foundCount, _ := d5search(tr.root, rect, 0, resultCallback)
3670	return foundCount
3671}
3672
3673/// Count the data elements in this container.  This is slow as no internal counter is maintained.
3674func (tr *d5RTree) Count() int {
3675	var count int
3676	d5countRec(tr.root, &count)
3677	return count
3678}
3679
3680/// Remove all entries from tree
3681func (tr *d5RTree) RemoveAll() {
3682	// Delete all existing nodes
3683	tr.root = &d5nodeT{}
3684}
3685
3686func d5countRec(node *d5nodeT, count *int) {
3687	if node.isInternalNode() { // not a leaf node
3688		for index := 0; index < node.count; index++ {
3689			d5countRec(node.branch[index].child, count)
3690		}
3691	} else { // A leaf node
3692		*count += node.count
3693	}
3694}
3695
3696// Inserts a new data rectangle into the index structure.
3697// Recursively descends tree, propagates splits back up.
3698// Returns 0 if node was not split.  Old node updated.
3699// If node was split, returns 1 and sets the pointer pointed to by
3700// new_node to point to the new node.  Old node updated to become one of two.
3701// The level argument specifies the number of steps up from the leaf
3702// level to insert; e.g. a data rectangle goes in at level = 0.
3703func d5insertRectRec(branch *d5branchT, node *d5nodeT, newNode **d5nodeT, level int) bool {
3704	// recurse until we reach the correct level for the new record. data records
3705	// will always be called with a_level == 0 (leaf)
3706	if node.level > level {
3707		// Still above level for insertion, go down tree recursively
3708		var otherNode *d5nodeT
3709		//var newBranch d5branchT
3710
3711		// find the optimal branch for this record
3712		index := d5pickBranch(&branch.rect, node)
3713
3714		// recursively insert this record into the picked branch
3715		childWasSplit := d5insertRectRec(branch, node.branch[index].child, &otherNode, level)
3716
3717		if !childWasSplit {
3718			// Child was not split. Merge the bounding box of the new record with the
3719			// existing bounding box
3720			node.branch[index].rect = d5combineRect(&branch.rect, &(node.branch[index].rect))
3721			return false
3722		} else {
3723			// Child was split. The old branches are now re-partitioned to two nodes
3724			// so we have to re-calculate the bounding boxes of each node
3725			node.branch[index].rect = d5nodeCover(node.branch[index].child)
3726			var newBranch d5branchT
3727			newBranch.child = otherNode
3728			newBranch.rect = d5nodeCover(otherNode)
3729
3730			// The old node is already a child of a_node. Now add the newly-created
3731			// node to a_node as well. a_node might be split because of that.
3732			return d5addBranch(&newBranch, node, newNode)
3733		}
3734	} else if node.level == level {
3735		// We have reached level for insertion. Add rect, split if necessary
3736		return d5addBranch(branch, node, newNode)
3737	} else {
3738		// Should never occur
3739		return false
3740	}
3741}
3742
3743// Insert a data rectangle into an index structure.
3744// d5insertRect provides for splitting the root;
3745// returns 1 if root was split, 0 if it was not.
3746// The level argument specifies the number of steps up from the leaf
3747// level to insert; e.g. a data rectangle goes in at level = 0.
3748// InsertRect2 does the recursion.
3749//
3750func d5insertRect(branch *d5branchT, root **d5nodeT, level int) bool {
3751	var newNode *d5nodeT
3752
3753	if d5insertRectRec(branch, *root, &newNode, level) { // Root split
3754
3755		// Grow tree taller and new root
3756		newRoot := &d5nodeT{}
3757		newRoot.level = (*root).level + 1
3758
3759		var newBranch d5branchT
3760
3761		// add old root node as a child of the new root
3762		newBranch.rect = d5nodeCover(*root)
3763		newBranch.child = *root
3764		d5addBranch(&newBranch, newRoot, nil)
3765
3766		// add the split node as a child of the new root
3767		newBranch.rect = d5nodeCover(newNode)
3768		newBranch.child = newNode
3769		d5addBranch(&newBranch, newRoot, nil)
3770
3771		// set the new root as the root node
3772		*root = newRoot
3773
3774		return true
3775	}
3776	return false
3777}
3778
3779// Find the smallest rectangle that includes all rectangles in branches of a node.
3780func d5nodeCover(node *d5nodeT) d5rectT {
3781	rect := node.branch[0].rect
3782	for index := 1; index < node.count; index++ {
3783		rect = d5combineRect(&rect, &(node.branch[index].rect))
3784	}
3785	return rect
3786}
3787
3788// Add a branch to a node.  Split the node if necessary.
3789// Returns 0 if node not split.  Old node updated.
3790// Returns 1 if node split, sets *new_node to address of new node.
3791// Old node updated, becomes one of two.
3792func d5addBranch(branch *d5branchT, node *d5nodeT, newNode **d5nodeT) bool {
3793	if node.count < d5maxNodes { // Split won't be necessary
3794		node.branch[node.count] = *branch
3795		node.count++
3796		return false
3797	} else {
3798		d5splitNode(node, branch, newNode)
3799		return true
3800	}
3801}
3802
3803// Disconnect a dependent node.
3804// Caller must return (or stop using iteration index) after this as count has changed
3805func d5disconnectBranch(node *d5nodeT, index int) {
3806	// Remove element by swapping with the last element to prevent gaps in array
3807	node.branch[index] = node.branch[node.count-1]
3808	node.branch[node.count-1].data = nil
3809	node.branch[node.count-1].child = nil
3810	node.count--
3811}
3812
3813// Pick a branch.  Pick the one that will need the smallest increase
3814// in area to accomodate the new rectangle.  This will result in the
3815// least total area for the covering rectangles in the current node.
3816// In case of a tie, pick the one which was smaller before, to get
3817// the best resolution when searching.
3818func d5pickBranch(rect *d5rectT, node *d5nodeT) int {
3819	var firstTime bool = true
3820	var increase float64
3821	var bestIncr float64 = -1
3822	var area float64
3823	var bestArea float64
3824	var best int
3825	var tempRect d5rectT
3826
3827	for index := 0; index < node.count; index++ {
3828		curRect := &node.branch[index].rect
3829		area = d5calcRectVolume(curRect)
3830		tempRect = d5combineRect(rect, curRect)
3831		increase = d5calcRectVolume(&tempRect) - area
3832		if (increase < bestIncr) || firstTime {
3833			best = index
3834			bestArea = area
3835			bestIncr = increase
3836			firstTime = false
3837		} else if (increase == bestIncr) && (area < bestArea) {
3838			best = index
3839			bestArea = area
3840			bestIncr = increase
3841		}
3842	}
3843	return best
3844}
3845
3846// Combine two rectangles into larger one containing both
3847func d5combineRect(rectA, rectB *d5rectT) d5rectT {
3848	var newRect d5rectT
3849
3850	for index := 0; index < d5numDims; index++ {
3851		newRect.min[index] = d5fmin(rectA.min[index], rectB.min[index])
3852		newRect.max[index] = d5fmax(rectA.max[index], rectB.max[index])
3853	}
3854
3855	return newRect
3856}
3857
3858// Split a node.
3859// Divides the nodes branches and the extra one between two nodes.
3860// Old node is one of the new ones, and one really new one is created.
3861// Tries more than one method for choosing a partition, uses best result.
3862func d5splitNode(node *d5nodeT, branch *d5branchT, newNode **d5nodeT) {
3863	// Could just use local here, but member or external is faster since it is reused
3864	var localVars d5partitionVarsT
3865	parVars := &localVars
3866
3867	// Load all the branches into a buffer, initialize old node
3868	d5getBranches(node, branch, parVars)
3869
3870	// Find partition
3871	d5choosePartition(parVars, d5minNodes)
3872
3873	// Create a new node to hold (about) half of the branches
3874	*newNode = &d5nodeT{}
3875	(*newNode).level = node.level
3876
3877	// Put branches from buffer into 2 nodes according to the chosen partition
3878	node.count = 0
3879	d5loadNodes(node, *newNode, parVars)
3880}
3881
3882// Calculate the n-dimensional volume of a rectangle
3883func d5rectVolume(rect *d5rectT) float64 {
3884	var volume float64 = 1
3885	for index := 0; index < d5numDims; index++ {
3886		volume *= rect.max[index] - rect.min[index]
3887	}
3888	return volume
3889}
3890
3891// The exact volume of the bounding sphere for the given d5rectT
3892func d5rectSphericalVolume(rect *d5rectT) float64 {
3893	var sumOfSquares float64 = 0
3894	var radius float64
3895
3896	for index := 0; index < d5numDims; index++ {
3897		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
3898		sumOfSquares += halfExtent * halfExtent
3899	}
3900
3901	radius = math.Sqrt(sumOfSquares)
3902
3903	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
3904	if d5numDims == 5 {
3905		return (radius * radius * radius * radius * radius * d5unitSphereVolume)
3906	} else if d5numDims == 4 {
3907		return (radius * radius * radius * radius * d5unitSphereVolume)
3908	} else if d5numDims == 3 {
3909		return (radius * radius * radius * d5unitSphereVolume)
3910	} else if d5numDims == 2 {
3911		return (radius * radius * d5unitSphereVolume)
3912	} else {
3913		return (math.Pow(radius, d5numDims) * d5unitSphereVolume)
3914	}
3915}
3916
3917// Use one of the methods to calculate retangle volume
3918func d5calcRectVolume(rect *d5rectT) float64 {
3919	if d5useSphericalVolume {
3920		return d5rectSphericalVolume(rect) // Slower but helps certain merge cases
3921	} else { // RTREE_USE_SPHERICAL_VOLUME
3922		return d5rectVolume(rect) // Faster but can cause poor merges
3923	} // RTREE_USE_SPHERICAL_VOLUME
3924}
3925
3926// Load branch buffer with branches from full node plus the extra branch.
3927func d5getBranches(node *d5nodeT, branch *d5branchT, parVars *d5partitionVarsT) {
3928	// Load the branch buffer
3929	for index := 0; index < d5maxNodes; index++ {
3930		parVars.branchBuf[index] = node.branch[index]
3931	}
3932	parVars.branchBuf[d5maxNodes] = *branch
3933	parVars.branchCount = d5maxNodes + 1
3934
3935	// Calculate rect containing all in the set
3936	parVars.coverSplit = parVars.branchBuf[0].rect
3937	for index := 1; index < d5maxNodes+1; index++ {
3938		parVars.coverSplit = d5combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
3939	}
3940	parVars.coverSplitArea = d5calcRectVolume(&parVars.coverSplit)
3941}
3942
3943// Method #0 for choosing a partition:
3944// As the seeds for the two groups, pick the two rects that would waste the
3945// most area if covered by a single rectangle, i.e. evidently the worst pair
3946// to have in the same group.
3947// Of the remaining, one at a time is chosen to be put in one of the two groups.
3948// The one chosen is the one with the greatest difference in area expansion
3949// depending on which group - the rect most strongly attracted to one group
3950// and repelled from the other.
3951// If one group gets too full (more would force other group to violate min
3952// fill requirement) then other group gets the rest.
3953// These last are the ones that can go in either group most easily.
3954func d5choosePartition(parVars *d5partitionVarsT, minFill int) {
3955	var biggestDiff float64
3956	var group, chosen, betterGroup int
3957
3958	d5initParVars(parVars, parVars.branchCount, minFill)
3959	d5pickSeeds(parVars)
3960
3961	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
3962		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
3963		(parVars.count[1] < (parVars.total - parVars.minFill)) {
3964		biggestDiff = -1
3965		for index := 0; index < parVars.total; index++ {
3966			if d5notTaken == parVars.partition[index] {
3967				curRect := &parVars.branchBuf[index].rect
3968				rect0 := d5combineRect(curRect, &parVars.cover[0])
3969				rect1 := d5combineRect(curRect, &parVars.cover[1])
3970				growth0 := d5calcRectVolume(&rect0) - parVars.area[0]
3971				growth1 := d5calcRectVolume(&rect1) - parVars.area[1]
3972				diff := growth1 - growth0
3973				if diff >= 0 {
3974					group = 0
3975				} else {
3976					group = 1
3977					diff = -diff
3978				}
3979
3980				if diff > biggestDiff {
3981					biggestDiff = diff
3982					chosen = index
3983					betterGroup = group
3984				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
3985					chosen = index
3986					betterGroup = group
3987				}
3988			}
3989		}
3990		d5classify(chosen, betterGroup, parVars)
3991	}
3992
3993	// If one group too full, put remaining rects in the other
3994	if (parVars.count[0] + parVars.count[1]) < parVars.total {
3995		if parVars.count[0] >= parVars.total-parVars.minFill {
3996			group = 1
3997		} else {
3998			group = 0
3999		}
4000		for index := 0; index < parVars.total; index++ {
4001			if d5notTaken == parVars.partition[index] {
4002				d5classify(index, group, parVars)
4003			}
4004		}
4005	}
4006}
4007
4008// Copy branches from the buffer into two nodes according to the partition.
4009func d5loadNodes(nodeA, nodeB *d5nodeT, parVars *d5partitionVarsT) {
4010	for index := 0; index < parVars.total; index++ {
4011		targetNodeIndex := parVars.partition[index]
4012		targetNodes := []*d5nodeT{nodeA, nodeB}
4013
4014		// It is assured that d5addBranch here will not cause a node split.
4015		d5addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
4016	}
4017}
4018
4019// Initialize a d5partitionVarsT structure.
4020func d5initParVars(parVars *d5partitionVarsT, maxRects, minFill int) {
4021	parVars.count[0] = 0
4022	parVars.count[1] = 0
4023	parVars.area[0] = 0
4024	parVars.area[1] = 0
4025	parVars.total = maxRects
4026	parVars.minFill = minFill
4027	for index := 0; index < maxRects; index++ {
4028		parVars.partition[index] = d5notTaken
4029	}
4030}
4031
4032func d5pickSeeds(parVars *d5partitionVarsT) {
4033	var seed0, seed1 int
4034	var worst, waste float64
4035	var area [d5maxNodes + 1]float64
4036
4037	for index := 0; index < parVars.total; index++ {
4038		area[index] = d5calcRectVolume(&parVars.branchBuf[index].rect)
4039	}
4040
4041	worst = -parVars.coverSplitArea - 1
4042	for indexA := 0; indexA < parVars.total-1; indexA++ {
4043		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
4044			oneRect := d5combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
4045			waste = d5calcRectVolume(&oneRect) - area[indexA] - area[indexB]
4046			if waste > worst {
4047				worst = waste
4048				seed0 = indexA
4049				seed1 = indexB
4050			}
4051		}
4052	}
4053
4054	d5classify(seed0, 0, parVars)
4055	d5classify(seed1, 1, parVars)
4056}
4057
4058// Put a branch in one of the groups.
4059func d5classify(index, group int, parVars *d5partitionVarsT) {
4060	parVars.partition[index] = group
4061
4062	// Calculate combined rect
4063	if parVars.count[group] == 0 {
4064		parVars.cover[group] = parVars.branchBuf[index].rect
4065	} else {
4066		parVars.cover[group] = d5combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
4067	}
4068
4069	// Calculate volume of combined rect
4070	parVars.area[group] = d5calcRectVolume(&parVars.cover[group])
4071
4072	parVars.count[group]++
4073}
4074
4075// Delete a data rectangle from an index structure.
4076// Pass in a pointer to a d5rectT, the tid of the record, ptr to ptr to root node.
4077// Returns 1 if record not found, 0 if success.
4078// d5removeRect provides for eliminating the root.
4079func d5removeRect(rect *d5rectT, id interface{}, root **d5nodeT) bool {
4080	var reInsertList *d5listNodeT
4081
4082	if !d5removeRectRec(rect, id, *root, &reInsertList) {
4083		// Found and deleted a data item
4084		// Reinsert any branches from eliminated nodes
4085		for reInsertList != nil {
4086			tempNode := reInsertList.node
4087
4088			for index := 0; index < tempNode.count; index++ {
4089				// TODO go over this code. should I use (tempNode->m_level - 1)?
4090				d5insertRect(&tempNode.branch[index], root, tempNode.level)
4091			}
4092			reInsertList = reInsertList.next
4093		}
4094
4095		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
4096		// if with while? In case there is a whole branch of redundant roots...
4097		if (*root).count == 1 && (*root).isInternalNode() {
4098			tempNode := (*root).branch[0].child
4099			*root = tempNode
4100		}
4101		return false
4102	} else {
4103		return true
4104	}
4105}
4106
4107// Delete a rectangle from non-root part of an index structure.
4108// Called by d5removeRect.  Descends tree recursively,
4109// merges branches on the way back up.
4110// Returns 1 if record not found, 0 if success.
4111func d5removeRectRec(rect *d5rectT, id interface{}, node *d5nodeT, listNode **d5listNodeT) bool {
4112	if node.isInternalNode() { // not a leaf node
4113		for index := 0; index < node.count; index++ {
4114			if d5overlap(*rect, node.branch[index].rect) {
4115				if !d5removeRectRec(rect, id, node.branch[index].child, listNode) {
4116					if node.branch[index].child.count >= d5minNodes {
4117						// child removed, just resize parent rect
4118						node.branch[index].rect = d5nodeCover(node.branch[index].child)
4119					} else {
4120						// child removed, not enough entries in node, eliminate node
4121						d5reInsert(node.branch[index].child, listNode)
4122						d5disconnectBranch(node, index) // Must return after this call as count has changed
4123					}
4124					return false
4125				}
4126			}
4127		}
4128		return true
4129	} else { // A leaf node
4130		for index := 0; index < node.count; index++ {
4131			if node.branch[index].data == id {
4132				d5disconnectBranch(node, index) // Must return after this call as count has changed
4133				return false
4134			}
4135		}
4136		return true
4137	}
4138}
4139
4140// Decide whether two rectangles d5overlap.
4141func d5overlap(rectA, rectB d5rectT) bool {
4142	for index := 0; index < d5numDims; index++ {
4143		if rectA.min[index] > rectB.max[index] ||
4144			rectB.min[index] > rectA.max[index] {
4145			return false
4146		}
4147	}
4148	return true
4149}
4150
4151// Add a node to the reinsertion list.  All its branches will later
4152// be reinserted into the index structure.
4153func d5reInsert(node *d5nodeT, listNode **d5listNodeT) {
4154	newListNode := &d5listNodeT{}
4155	newListNode.node = node
4156	newListNode.next = *listNode
4157	*listNode = newListNode
4158}
4159
4160// d5search in an index tree or subtree for all data retangles that d5overlap the argument rectangle.
4161func d5search(node *d5nodeT, rect d5rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
4162	if node.isInternalNode() {
4163		// This is an internal node in the tree
4164		for index := 0; index < node.count; index++ {
4165			if d5overlap(rect, node.branch[index].rect) {
4166				var ok bool
4167				foundCount, ok = d5search(node.branch[index].child, rect, foundCount, resultCallback)
4168				if !ok {
4169					// The callback indicated to stop searching
4170					return foundCount, false
4171				}
4172			}
4173		}
4174	} else {
4175		// This is a leaf node
4176		for index := 0; index < node.count; index++ {
4177			if d5overlap(rect, node.branch[index].rect) {
4178				id := node.branch[index].data
4179				foundCount++
4180				if !resultCallback(id) {
4181					return foundCount, false // Don't continue searching
4182				}
4183
4184			}
4185		}
4186	}
4187	return foundCount, true // Continue searching
4188}
4189
4190func d6fmin(a, b float64) float64 {
4191	if a < b {
4192		return a
4193	}
4194	return b
4195}
4196func d6fmax(a, b float64) float64 {
4197	if a > b {
4198		return a
4199	}
4200	return b
4201}
4202
4203const (
4204	d6numDims            = 6
4205	d6maxNodes           = 8
4206	d6minNodes           = d6maxNodes / 2
4207	d6useSphericalVolume = true // Better split classification, may be slower on some systems
4208)
4209
4210var d6unitSphereVolume = []float64{
4211	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
4212	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
4213	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
4214	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
4215	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
4216	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
4217	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
4218}[d6numDims]
4219
4220type d6RTree struct {
4221	root *d6nodeT ///< Root of tree
4222}
4223
4224/// Minimal bounding rectangle (n-dimensional)
4225type d6rectT struct {
4226	min [d6numDims]float64 ///< Min dimensions of bounding box
4227	max [d6numDims]float64 ///< Max dimensions of bounding box
4228}
4229
4230/// May be data or may be another subtree
4231/// The parents level determines this.
4232/// If the parents level is 0, then this is data
4233type d6branchT struct {
4234	rect  d6rectT     ///< Bounds
4235	child *d6nodeT    ///< Child node
4236	data  interface{} ///< Data Id or Ptr
4237}
4238
4239/// d6nodeT for each branch level
4240type d6nodeT struct {
4241	count  int                   ///< Count
4242	level  int                   ///< Leaf is zero, others positive
4243	branch [d6maxNodes]d6branchT ///< Branch
4244}
4245
4246func (node *d6nodeT) isInternalNode() bool {
4247	return (node.level > 0) // Not a leaf, but a internal node
4248}
4249func (node *d6nodeT) isLeaf() bool {
4250	return (node.level == 0) // A leaf, contains data
4251}
4252
4253/// A link list of nodes for reinsertion after a delete operation
4254type d6listNodeT struct {
4255	next *d6listNodeT ///< Next in list
4256	node *d6nodeT     ///< Node
4257}
4258
4259const d6notTaken = -1 // indicates that position
4260
4261/// Variables for finding a split partition
4262type d6partitionVarsT struct {
4263	partition [d6maxNodes + 1]int
4264	total     int
4265	minFill   int
4266	count     [2]int
4267	cover     [2]d6rectT
4268	area      [2]float64
4269
4270	branchBuf      [d6maxNodes + 1]d6branchT
4271	branchCount    int
4272	coverSplit     d6rectT
4273	coverSplitArea float64
4274}
4275
4276func d6New() *d6RTree {
4277	// We only support machine word size simple data type eg. integer index or object pointer.
4278	// Since we are storing as union with non data branch
4279	return &d6RTree{
4280		root: &d6nodeT{},
4281	}
4282}
4283
4284/// Insert entry
4285/// \param a_min Min of bounding rect
4286/// \param a_max Max of bounding rect
4287/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
4288func (tr *d6RTree) Insert(min, max [d6numDims]float64, dataId interface{}) {
4289	var branch d6branchT
4290	branch.data = dataId
4291	for axis := 0; axis < d6numDims; axis++ {
4292		branch.rect.min[axis] = min[axis]
4293		branch.rect.max[axis] = max[axis]
4294	}
4295	d6insertRect(&branch, &tr.root, 0)
4296}
4297
4298/// Remove entry
4299/// \param a_min Min of bounding rect
4300/// \param a_max Max of bounding rect
4301/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
4302func (tr *d6RTree) Remove(min, max [d6numDims]float64, dataId interface{}) {
4303	var rect d6rectT
4304	for axis := 0; axis < d6numDims; axis++ {
4305		rect.min[axis] = min[axis]
4306		rect.max[axis] = max[axis]
4307	}
4308	d6removeRect(&rect, dataId, &tr.root)
4309}
4310
4311/// Find all within d6search rectangle
4312/// \param a_min Min of d6search bounding rect
4313/// \param a_max Max of d6search bounding rect
4314/// \param a_searchResult d6search result array.  Caller should set grow size. Function will reset, not append to array.
4315/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
4316/// \param a_context User context to pass as parameter to a_resultCallback
4317/// \return Returns the number of entries found
4318func (tr *d6RTree) Search(min, max [d6numDims]float64, resultCallback func(data interface{}) bool) int {
4319	var rect d6rectT
4320	for axis := 0; axis < d6numDims; axis++ {
4321		rect.min[axis] = min[axis]
4322		rect.max[axis] = max[axis]
4323	}
4324	foundCount, _ := d6search(tr.root, rect, 0, resultCallback)
4325	return foundCount
4326}
4327
4328/// Count the data elements in this container.  This is slow as no internal counter is maintained.
4329func (tr *d6RTree) Count() int {
4330	var count int
4331	d6countRec(tr.root, &count)
4332	return count
4333}
4334
4335/// Remove all entries from tree
4336func (tr *d6RTree) RemoveAll() {
4337	// Delete all existing nodes
4338	tr.root = &d6nodeT{}
4339}
4340
4341func d6countRec(node *d6nodeT, count *int) {
4342	if node.isInternalNode() { // not a leaf node
4343		for index := 0; index < node.count; index++ {
4344			d6countRec(node.branch[index].child, count)
4345		}
4346	} else { // A leaf node
4347		*count += node.count
4348	}
4349}
4350
4351// Inserts a new data rectangle into the index structure.
4352// Recursively descends tree, propagates splits back up.
4353// Returns 0 if node was not split.  Old node updated.
4354// If node was split, returns 1 and sets the pointer pointed to by
4355// new_node to point to the new node.  Old node updated to become one of two.
4356// The level argument specifies the number of steps up from the leaf
4357// level to insert; e.g. a data rectangle goes in at level = 0.
4358func d6insertRectRec(branch *d6branchT, node *d6nodeT, newNode **d6nodeT, level int) bool {
4359	// recurse until we reach the correct level for the new record. data records
4360	// will always be called with a_level == 0 (leaf)
4361	if node.level > level {
4362		// Still above level for insertion, go down tree recursively
4363		var otherNode *d6nodeT
4364		//var newBranch d6branchT
4365
4366		// find the optimal branch for this record
4367		index := d6pickBranch(&branch.rect, node)
4368
4369		// recursively insert this record into the picked branch
4370		childWasSplit := d6insertRectRec(branch, node.branch[index].child, &otherNode, level)
4371
4372		if !childWasSplit {
4373			// Child was not split. Merge the bounding box of the new record with the
4374			// existing bounding box
4375			node.branch[index].rect = d6combineRect(&branch.rect, &(node.branch[index].rect))
4376			return false
4377		} else {
4378			// Child was split. The old branches are now re-partitioned to two nodes
4379			// so we have to re-calculate the bounding boxes of each node
4380			node.branch[index].rect = d6nodeCover(node.branch[index].child)
4381			var newBranch d6branchT
4382			newBranch.child = otherNode
4383			newBranch.rect = d6nodeCover(otherNode)
4384
4385			// The old node is already a child of a_node. Now add the newly-created
4386			// node to a_node as well. a_node might be split because of that.
4387			return d6addBranch(&newBranch, node, newNode)
4388		}
4389	} else if node.level == level {
4390		// We have reached level for insertion. Add rect, split if necessary
4391		return d6addBranch(branch, node, newNode)
4392	} else {
4393		// Should never occur
4394		return false
4395	}
4396}
4397
4398// Insert a data rectangle into an index structure.
4399// d6insertRect provides for splitting the root;
4400// returns 1 if root was split, 0 if it was not.
4401// The level argument specifies the number of steps up from the leaf
4402// level to insert; e.g. a data rectangle goes in at level = 0.
4403// InsertRect2 does the recursion.
4404//
4405func d6insertRect(branch *d6branchT, root **d6nodeT, level int) bool {
4406	var newNode *d6nodeT
4407
4408	if d6insertRectRec(branch, *root, &newNode, level) { // Root split
4409
4410		// Grow tree taller and new root
4411		newRoot := &d6nodeT{}
4412		newRoot.level = (*root).level + 1
4413
4414		var newBranch d6branchT
4415
4416		// add old root node as a child of the new root
4417		newBranch.rect = d6nodeCover(*root)
4418		newBranch.child = *root
4419		d6addBranch(&newBranch, newRoot, nil)
4420
4421		// add the split node as a child of the new root
4422		newBranch.rect = d6nodeCover(newNode)
4423		newBranch.child = newNode
4424		d6addBranch(&newBranch, newRoot, nil)
4425
4426		// set the new root as the root node
4427		*root = newRoot
4428
4429		return true
4430	}
4431	return false
4432}
4433
4434// Find the smallest rectangle that includes all rectangles in branches of a node.
4435func d6nodeCover(node *d6nodeT) d6rectT {
4436	rect := node.branch[0].rect
4437	for index := 1; index < node.count; index++ {
4438		rect = d6combineRect(&rect, &(node.branch[index].rect))
4439	}
4440	return rect
4441}
4442
4443// Add a branch to a node.  Split the node if necessary.
4444// Returns 0 if node not split.  Old node updated.
4445// Returns 1 if node split, sets *new_node to address of new node.
4446// Old node updated, becomes one of two.
4447func d6addBranch(branch *d6branchT, node *d6nodeT, newNode **d6nodeT) bool {
4448	if node.count < d6maxNodes { // Split won't be necessary
4449		node.branch[node.count] = *branch
4450		node.count++
4451		return false
4452	} else {
4453		d6splitNode(node, branch, newNode)
4454		return true
4455	}
4456}
4457
4458// Disconnect a dependent node.
4459// Caller must return (or stop using iteration index) after this as count has changed
4460func d6disconnectBranch(node *d6nodeT, index int) {
4461	// Remove element by swapping with the last element to prevent gaps in array
4462	node.branch[index] = node.branch[node.count-1]
4463	node.branch[node.count-1].data = nil
4464	node.branch[node.count-1].child = nil
4465	node.count--
4466}
4467
4468// Pick a branch.  Pick the one that will need the smallest increase
4469// in area to accomodate the new rectangle.  This will result in the
4470// least total area for the covering rectangles in the current node.
4471// In case of a tie, pick the one which was smaller before, to get
4472// the best resolution when searching.
4473func d6pickBranch(rect *d6rectT, node *d6nodeT) int {
4474	var firstTime bool = true
4475	var increase float64
4476	var bestIncr float64 = -1
4477	var area float64
4478	var bestArea float64
4479	var best int
4480	var tempRect d6rectT
4481
4482	for index := 0; index < node.count; index++ {
4483		curRect := &node.branch[index].rect
4484		area = d6calcRectVolume(curRect)
4485		tempRect = d6combineRect(rect, curRect)
4486		increase = d6calcRectVolume(&tempRect) - area
4487		if (increase < bestIncr) || firstTime {
4488			best = index
4489			bestArea = area
4490			bestIncr = increase
4491			firstTime = false
4492		} else if (increase == bestIncr) && (area < bestArea) {
4493			best = index
4494			bestArea = area
4495			bestIncr = increase
4496		}
4497	}
4498	return best
4499}
4500
4501// Combine two rectangles into larger one containing both
4502func d6combineRect(rectA, rectB *d6rectT) d6rectT {
4503	var newRect d6rectT
4504
4505	for index := 0; index < d6numDims; index++ {
4506		newRect.min[index] = d6fmin(rectA.min[index], rectB.min[index])
4507		newRect.max[index] = d6fmax(rectA.max[index], rectB.max[index])
4508	}
4509
4510	return newRect
4511}
4512
4513// Split a node.
4514// Divides the nodes branches and the extra one between two nodes.
4515// Old node is one of the new ones, and one really new one is created.
4516// Tries more than one method for choosing a partition, uses best result.
4517func d6splitNode(node *d6nodeT, branch *d6branchT, newNode **d6nodeT) {
4518	// Could just use local here, but member or external is faster since it is reused
4519	var localVars d6partitionVarsT
4520	parVars := &localVars
4521
4522	// Load all the branches into a buffer, initialize old node
4523	d6getBranches(node, branch, parVars)
4524
4525	// Find partition
4526	d6choosePartition(parVars, d6minNodes)
4527
4528	// Create a new node to hold (about) half of the branches
4529	*newNode = &d6nodeT{}
4530	(*newNode).level = node.level
4531
4532	// Put branches from buffer into 2 nodes according to the chosen partition
4533	node.count = 0
4534	d6loadNodes(node, *newNode, parVars)
4535}
4536
4537// Calculate the n-dimensional volume of a rectangle
4538func d6rectVolume(rect *d6rectT) float64 {
4539	var volume float64 = 1
4540	for index := 0; index < d6numDims; index++ {
4541		volume *= rect.max[index] - rect.min[index]
4542	}
4543	return volume
4544}
4545
4546// The exact volume of the bounding sphere for the given d6rectT
4547func d6rectSphericalVolume(rect *d6rectT) float64 {
4548	var sumOfSquares float64 = 0
4549	var radius float64
4550
4551	for index := 0; index < d6numDims; index++ {
4552		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
4553		sumOfSquares += halfExtent * halfExtent
4554	}
4555
4556	radius = math.Sqrt(sumOfSquares)
4557
4558	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
4559	if d6numDims == 5 {
4560		return (radius * radius * radius * radius * radius * d6unitSphereVolume)
4561	} else if d6numDims == 4 {
4562		return (radius * radius * radius * radius * d6unitSphereVolume)
4563	} else if d6numDims == 3 {
4564		return (radius * radius * radius * d6unitSphereVolume)
4565	} else if d6numDims == 2 {
4566		return (radius * radius * d6unitSphereVolume)
4567	} else {
4568		return (math.Pow(radius, d6numDims) * d6unitSphereVolume)
4569	}
4570}
4571
4572// Use one of the methods to calculate retangle volume
4573func d6calcRectVolume(rect *d6rectT) float64 {
4574	if d6useSphericalVolume {
4575		return d6rectSphericalVolume(rect) // Slower but helps certain merge cases
4576	} else { // RTREE_USE_SPHERICAL_VOLUME
4577		return d6rectVolume(rect) // Faster but can cause poor merges
4578	} // RTREE_USE_SPHERICAL_VOLUME
4579}
4580
4581// Load branch buffer with branches from full node plus the extra branch.
4582func d6getBranches(node *d6nodeT, branch *d6branchT, parVars *d6partitionVarsT) {
4583	// Load the branch buffer
4584	for index := 0; index < d6maxNodes; index++ {
4585		parVars.branchBuf[index] = node.branch[index]
4586	}
4587	parVars.branchBuf[d6maxNodes] = *branch
4588	parVars.branchCount = d6maxNodes + 1
4589
4590	// Calculate rect containing all in the set
4591	parVars.coverSplit = parVars.branchBuf[0].rect
4592	for index := 1; index < d6maxNodes+1; index++ {
4593		parVars.coverSplit = d6combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
4594	}
4595	parVars.coverSplitArea = d6calcRectVolume(&parVars.coverSplit)
4596}
4597
4598// Method #0 for choosing a partition:
4599// As the seeds for the two groups, pick the two rects that would waste the
4600// most area if covered by a single rectangle, i.e. evidently the worst pair
4601// to have in the same group.
4602// Of the remaining, one at a time is chosen to be put in one of the two groups.
4603// The one chosen is the one with the greatest difference in area expansion
4604// depending on which group - the rect most strongly attracted to one group
4605// and repelled from the other.
4606// If one group gets too full (more would force other group to violate min
4607// fill requirement) then other group gets the rest.
4608// These last are the ones that can go in either group most easily.
4609func d6choosePartition(parVars *d6partitionVarsT, minFill int) {
4610	var biggestDiff float64
4611	var group, chosen, betterGroup int
4612
4613	d6initParVars(parVars, parVars.branchCount, minFill)
4614	d6pickSeeds(parVars)
4615
4616	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
4617		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
4618		(parVars.count[1] < (parVars.total - parVars.minFill)) {
4619		biggestDiff = -1
4620		for index := 0; index < parVars.total; index++ {
4621			if d6notTaken == parVars.partition[index] {
4622				curRect := &parVars.branchBuf[index].rect
4623				rect0 := d6combineRect(curRect, &parVars.cover[0])
4624				rect1 := d6combineRect(curRect, &parVars.cover[1])
4625				growth0 := d6calcRectVolume(&rect0) - parVars.area[0]
4626				growth1 := d6calcRectVolume(&rect1) - parVars.area[1]
4627				diff := growth1 - growth0
4628				if diff >= 0 {
4629					group = 0
4630				} else {
4631					group = 1
4632					diff = -diff
4633				}
4634
4635				if diff > biggestDiff {
4636					biggestDiff = diff
4637					chosen = index
4638					betterGroup = group
4639				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
4640					chosen = index
4641					betterGroup = group
4642				}
4643			}
4644		}
4645		d6classify(chosen, betterGroup, parVars)
4646	}
4647
4648	// If one group too full, put remaining rects in the other
4649	if (parVars.count[0] + parVars.count[1]) < parVars.total {
4650		if parVars.count[0] >= parVars.total-parVars.minFill {
4651			group = 1
4652		} else {
4653			group = 0
4654		}
4655		for index := 0; index < parVars.total; index++ {
4656			if d6notTaken == parVars.partition[index] {
4657				d6classify(index, group, parVars)
4658			}
4659		}
4660	}
4661}
4662
4663// Copy branches from the buffer into two nodes according to the partition.
4664func d6loadNodes(nodeA, nodeB *d6nodeT, parVars *d6partitionVarsT) {
4665	for index := 0; index < parVars.total; index++ {
4666		targetNodeIndex := parVars.partition[index]
4667		targetNodes := []*d6nodeT{nodeA, nodeB}
4668
4669		// It is assured that d6addBranch here will not cause a node split.
4670		d6addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
4671	}
4672}
4673
4674// Initialize a d6partitionVarsT structure.
4675func d6initParVars(parVars *d6partitionVarsT, maxRects, minFill int) {
4676	parVars.count[0] = 0
4677	parVars.count[1] = 0
4678	parVars.area[0] = 0
4679	parVars.area[1] = 0
4680	parVars.total = maxRects
4681	parVars.minFill = minFill
4682	for index := 0; index < maxRects; index++ {
4683		parVars.partition[index] = d6notTaken
4684	}
4685}
4686
4687func d6pickSeeds(parVars *d6partitionVarsT) {
4688	var seed0, seed1 int
4689	var worst, waste float64
4690	var area [d6maxNodes + 1]float64
4691
4692	for index := 0; index < parVars.total; index++ {
4693		area[index] = d6calcRectVolume(&parVars.branchBuf[index].rect)
4694	}
4695
4696	worst = -parVars.coverSplitArea - 1
4697	for indexA := 0; indexA < parVars.total-1; indexA++ {
4698		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
4699			oneRect := d6combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
4700			waste = d6calcRectVolume(&oneRect) - area[indexA] - area[indexB]
4701			if waste > worst {
4702				worst = waste
4703				seed0 = indexA
4704				seed1 = indexB
4705			}
4706		}
4707	}
4708
4709	d6classify(seed0, 0, parVars)
4710	d6classify(seed1, 1, parVars)
4711}
4712
4713// Put a branch in one of the groups.
4714func d6classify(index, group int, parVars *d6partitionVarsT) {
4715	parVars.partition[index] = group
4716
4717	// Calculate combined rect
4718	if parVars.count[group] == 0 {
4719		parVars.cover[group] = parVars.branchBuf[index].rect
4720	} else {
4721		parVars.cover[group] = d6combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
4722	}
4723
4724	// Calculate volume of combined rect
4725	parVars.area[group] = d6calcRectVolume(&parVars.cover[group])
4726
4727	parVars.count[group]++
4728}
4729
4730// Delete a data rectangle from an index structure.
4731// Pass in a pointer to a d6rectT, the tid of the record, ptr to ptr to root node.
4732// Returns 1 if record not found, 0 if success.
4733// d6removeRect provides for eliminating the root.
4734func d6removeRect(rect *d6rectT, id interface{}, root **d6nodeT) bool {
4735	var reInsertList *d6listNodeT
4736
4737	if !d6removeRectRec(rect, id, *root, &reInsertList) {
4738		// Found and deleted a data item
4739		// Reinsert any branches from eliminated nodes
4740		for reInsertList != nil {
4741			tempNode := reInsertList.node
4742
4743			for index := 0; index < tempNode.count; index++ {
4744				// TODO go over this code. should I use (tempNode->m_level - 1)?
4745				d6insertRect(&tempNode.branch[index], root, tempNode.level)
4746			}
4747			reInsertList = reInsertList.next
4748		}
4749
4750		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
4751		// if with while? In case there is a whole branch of redundant roots...
4752		if (*root).count == 1 && (*root).isInternalNode() {
4753			tempNode := (*root).branch[0].child
4754			*root = tempNode
4755		}
4756		return false
4757	} else {
4758		return true
4759	}
4760}
4761
4762// Delete a rectangle from non-root part of an index structure.
4763// Called by d6removeRect.  Descends tree recursively,
4764// merges branches on the way back up.
4765// Returns 1 if record not found, 0 if success.
4766func d6removeRectRec(rect *d6rectT, id interface{}, node *d6nodeT, listNode **d6listNodeT) bool {
4767	if node.isInternalNode() { // not a leaf node
4768		for index := 0; index < node.count; index++ {
4769			if d6overlap(*rect, node.branch[index].rect) {
4770				if !d6removeRectRec(rect, id, node.branch[index].child, listNode) {
4771					if node.branch[index].child.count >= d6minNodes {
4772						// child removed, just resize parent rect
4773						node.branch[index].rect = d6nodeCover(node.branch[index].child)
4774					} else {
4775						// child removed, not enough entries in node, eliminate node
4776						d6reInsert(node.branch[index].child, listNode)
4777						d6disconnectBranch(node, index) // Must return after this call as count has changed
4778					}
4779					return false
4780				}
4781			}
4782		}
4783		return true
4784	} else { // A leaf node
4785		for index := 0; index < node.count; index++ {
4786			if node.branch[index].data == id {
4787				d6disconnectBranch(node, index) // Must return after this call as count has changed
4788				return false
4789			}
4790		}
4791		return true
4792	}
4793}
4794
4795// Decide whether two rectangles d6overlap.
4796func d6overlap(rectA, rectB d6rectT) bool {
4797	for index := 0; index < d6numDims; index++ {
4798		if rectA.min[index] > rectB.max[index] ||
4799			rectB.min[index] > rectA.max[index] {
4800			return false
4801		}
4802	}
4803	return true
4804}
4805
4806// Add a node to the reinsertion list.  All its branches will later
4807// be reinserted into the index structure.
4808func d6reInsert(node *d6nodeT, listNode **d6listNodeT) {
4809	newListNode := &d6listNodeT{}
4810	newListNode.node = node
4811	newListNode.next = *listNode
4812	*listNode = newListNode
4813}
4814
4815// d6search in an index tree or subtree for all data retangles that d6overlap the argument rectangle.
4816func d6search(node *d6nodeT, rect d6rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
4817	if node.isInternalNode() {
4818		// This is an internal node in the tree
4819		for index := 0; index < node.count; index++ {
4820			if d6overlap(rect, node.branch[index].rect) {
4821				var ok bool
4822				foundCount, ok = d6search(node.branch[index].child, rect, foundCount, resultCallback)
4823				if !ok {
4824					// The callback indicated to stop searching
4825					return foundCount, false
4826				}
4827			}
4828		}
4829	} else {
4830		// This is a leaf node
4831		for index := 0; index < node.count; index++ {
4832			if d6overlap(rect, node.branch[index].rect) {
4833				id := node.branch[index].data
4834				foundCount++
4835				if !resultCallback(id) {
4836					return foundCount, false // Don't continue searching
4837				}
4838
4839			}
4840		}
4841	}
4842	return foundCount, true // Continue searching
4843}
4844
4845func d7fmin(a, b float64) float64 {
4846	if a < b {
4847		return a
4848	}
4849	return b
4850}
4851func d7fmax(a, b float64) float64 {
4852	if a > b {
4853		return a
4854	}
4855	return b
4856}
4857
4858const (
4859	d7numDims            = 7
4860	d7maxNodes           = 8
4861	d7minNodes           = d7maxNodes / 2
4862	d7useSphericalVolume = true // Better split classification, may be slower on some systems
4863)
4864
4865var d7unitSphereVolume = []float64{
4866	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
4867	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
4868	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
4869	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
4870	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
4871	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
4872	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
4873}[d7numDims]
4874
4875type d7RTree struct {
4876	root *d7nodeT ///< Root of tree
4877}
4878
4879/// Minimal bounding rectangle (n-dimensional)
4880type d7rectT struct {
4881	min [d7numDims]float64 ///< Min dimensions of bounding box
4882	max [d7numDims]float64 ///< Max dimensions of bounding box
4883}
4884
4885/// May be data or may be another subtree
4886/// The parents level determines this.
4887/// If the parents level is 0, then this is data
4888type d7branchT struct {
4889	rect  d7rectT     ///< Bounds
4890	child *d7nodeT    ///< Child node
4891	data  interface{} ///< Data Id or Ptr
4892}
4893
4894/// d7nodeT for each branch level
4895type d7nodeT struct {
4896	count  int                   ///< Count
4897	level  int                   ///< Leaf is zero, others positive
4898	branch [d7maxNodes]d7branchT ///< Branch
4899}
4900
4901func (node *d7nodeT) isInternalNode() bool {
4902	return (node.level > 0) // Not a leaf, but a internal node
4903}
4904func (node *d7nodeT) isLeaf() bool {
4905	return (node.level == 0) // A leaf, contains data
4906}
4907
4908/// A link list of nodes for reinsertion after a delete operation
4909type d7listNodeT struct {
4910	next *d7listNodeT ///< Next in list
4911	node *d7nodeT     ///< Node
4912}
4913
4914const d7notTaken = -1 // indicates that position
4915
4916/// Variables for finding a split partition
4917type d7partitionVarsT struct {
4918	partition [d7maxNodes + 1]int
4919	total     int
4920	minFill   int
4921	count     [2]int
4922	cover     [2]d7rectT
4923	area      [2]float64
4924
4925	branchBuf      [d7maxNodes + 1]d7branchT
4926	branchCount    int
4927	coverSplit     d7rectT
4928	coverSplitArea float64
4929}
4930
4931func d7New() *d7RTree {
4932	// We only support machine word size simple data type eg. integer index or object pointer.
4933	// Since we are storing as union with non data branch
4934	return &d7RTree{
4935		root: &d7nodeT{},
4936	}
4937}
4938
4939/// Insert entry
4940/// \param a_min Min of bounding rect
4941/// \param a_max Max of bounding rect
4942/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
4943func (tr *d7RTree) Insert(min, max [d7numDims]float64, dataId interface{}) {
4944	var branch d7branchT
4945	branch.data = dataId
4946	for axis := 0; axis < d7numDims; axis++ {
4947		branch.rect.min[axis] = min[axis]
4948		branch.rect.max[axis] = max[axis]
4949	}
4950	d7insertRect(&branch, &tr.root, 0)
4951}
4952
4953/// Remove entry
4954/// \param a_min Min of bounding rect
4955/// \param a_max Max of bounding rect
4956/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
4957func (tr *d7RTree) Remove(min, max [d7numDims]float64, dataId interface{}) {
4958	var rect d7rectT
4959	for axis := 0; axis < d7numDims; axis++ {
4960		rect.min[axis] = min[axis]
4961		rect.max[axis] = max[axis]
4962	}
4963	d7removeRect(&rect, dataId, &tr.root)
4964}
4965
4966/// Find all within d7search rectangle
4967/// \param a_min Min of d7search bounding rect
4968/// \param a_max Max of d7search bounding rect
4969/// \param a_searchResult d7search result array.  Caller should set grow size. Function will reset, not append to array.
4970/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
4971/// \param a_context User context to pass as parameter to a_resultCallback
4972/// \return Returns the number of entries found
4973func (tr *d7RTree) Search(min, max [d7numDims]float64, resultCallback func(data interface{}) bool) int {
4974	var rect d7rectT
4975	for axis := 0; axis < d7numDims; axis++ {
4976		rect.min[axis] = min[axis]
4977		rect.max[axis] = max[axis]
4978	}
4979	foundCount, _ := d7search(tr.root, rect, 0, resultCallback)
4980	return foundCount
4981}
4982
4983/// Count the data elements in this container.  This is slow as no internal counter is maintained.
4984func (tr *d7RTree) Count() int {
4985	var count int
4986	d7countRec(tr.root, &count)
4987	return count
4988}
4989
4990/// Remove all entries from tree
4991func (tr *d7RTree) RemoveAll() {
4992	// Delete all existing nodes
4993	tr.root = &d7nodeT{}
4994}
4995
4996func d7countRec(node *d7nodeT, count *int) {
4997	if node.isInternalNode() { // not a leaf node
4998		for index := 0; index < node.count; index++ {
4999			d7countRec(node.branch[index].child, count)
5000		}
5001	} else { // A leaf node
5002		*count += node.count
5003	}
5004}
5005
5006// Inserts a new data rectangle into the index structure.
5007// Recursively descends tree, propagates splits back up.
5008// Returns 0 if node was not split.  Old node updated.
5009// If node was split, returns 1 and sets the pointer pointed to by
5010// new_node to point to the new node.  Old node updated to become one of two.
5011// The level argument specifies the number of steps up from the leaf
5012// level to insert; e.g. a data rectangle goes in at level = 0.
5013func d7insertRectRec(branch *d7branchT, node *d7nodeT, newNode **d7nodeT, level int) bool {
5014	// recurse until we reach the correct level for the new record. data records
5015	// will always be called with a_level == 0 (leaf)
5016	if node.level > level {
5017		// Still above level for insertion, go down tree recursively
5018		var otherNode *d7nodeT
5019		//var newBranch d7branchT
5020
5021		// find the optimal branch for this record
5022		index := d7pickBranch(&branch.rect, node)
5023
5024		// recursively insert this record into the picked branch
5025		childWasSplit := d7insertRectRec(branch, node.branch[index].child, &otherNode, level)
5026
5027		if !childWasSplit {
5028			// Child was not split. Merge the bounding box of the new record with the
5029			// existing bounding box
5030			node.branch[index].rect = d7combineRect(&branch.rect, &(node.branch[index].rect))
5031			return false
5032		} else {
5033			// Child was split. The old branches are now re-partitioned to two nodes
5034			// so we have to re-calculate the bounding boxes of each node
5035			node.branch[index].rect = d7nodeCover(node.branch[index].child)
5036			var newBranch d7branchT
5037			newBranch.child = otherNode
5038			newBranch.rect = d7nodeCover(otherNode)
5039
5040			// The old node is already a child of a_node. Now add the newly-created
5041			// node to a_node as well. a_node might be split because of that.
5042			return d7addBranch(&newBranch, node, newNode)
5043		}
5044	} else if node.level == level {
5045		// We have reached level for insertion. Add rect, split if necessary
5046		return d7addBranch(branch, node, newNode)
5047	} else {
5048		// Should never occur
5049		return false
5050	}
5051}
5052
5053// Insert a data rectangle into an index structure.
5054// d7insertRect provides for splitting the root;
5055// returns 1 if root was split, 0 if it was not.
5056// The level argument specifies the number of steps up from the leaf
5057// level to insert; e.g. a data rectangle goes in at level = 0.
5058// InsertRect2 does the recursion.
5059//
5060func d7insertRect(branch *d7branchT, root **d7nodeT, level int) bool {
5061	var newNode *d7nodeT
5062
5063	if d7insertRectRec(branch, *root, &newNode, level) { // Root split
5064
5065		// Grow tree taller and new root
5066		newRoot := &d7nodeT{}
5067		newRoot.level = (*root).level + 1
5068
5069		var newBranch d7branchT
5070
5071		// add old root node as a child of the new root
5072		newBranch.rect = d7nodeCover(*root)
5073		newBranch.child = *root
5074		d7addBranch(&newBranch, newRoot, nil)
5075
5076		// add the split node as a child of the new root
5077		newBranch.rect = d7nodeCover(newNode)
5078		newBranch.child = newNode
5079		d7addBranch(&newBranch, newRoot, nil)
5080
5081		// set the new root as the root node
5082		*root = newRoot
5083
5084		return true
5085	}
5086	return false
5087}
5088
5089// Find the smallest rectangle that includes all rectangles in branches of a node.
5090func d7nodeCover(node *d7nodeT) d7rectT {
5091	rect := node.branch[0].rect
5092	for index := 1; index < node.count; index++ {
5093		rect = d7combineRect(&rect, &(node.branch[index].rect))
5094	}
5095	return rect
5096}
5097
5098// Add a branch to a node.  Split the node if necessary.
5099// Returns 0 if node not split.  Old node updated.
5100// Returns 1 if node split, sets *new_node to address of new node.
5101// Old node updated, becomes one of two.
5102func d7addBranch(branch *d7branchT, node *d7nodeT, newNode **d7nodeT) bool {
5103	if node.count < d7maxNodes { // Split won't be necessary
5104		node.branch[node.count] = *branch
5105		node.count++
5106		return false
5107	} else {
5108		d7splitNode(node, branch, newNode)
5109		return true
5110	}
5111}
5112
5113// Disconnect a dependent node.
5114// Caller must return (or stop using iteration index) after this as count has changed
5115func d7disconnectBranch(node *d7nodeT, index int) {
5116	// Remove element by swapping with the last element to prevent gaps in array
5117	node.branch[index] = node.branch[node.count-1]
5118	node.branch[node.count-1].data = nil
5119	node.branch[node.count-1].child = nil
5120	node.count--
5121}
5122
5123// Pick a branch.  Pick the one that will need the smallest increase
5124// in area to accomodate the new rectangle.  This will result in the
5125// least total area for the covering rectangles in the current node.
5126// In case of a tie, pick the one which was smaller before, to get
5127// the best resolution when searching.
5128func d7pickBranch(rect *d7rectT, node *d7nodeT) int {
5129	var firstTime bool = true
5130	var increase float64
5131	var bestIncr float64 = -1
5132	var area float64
5133	var bestArea float64
5134	var best int
5135	var tempRect d7rectT
5136
5137	for index := 0; index < node.count; index++ {
5138		curRect := &node.branch[index].rect
5139		area = d7calcRectVolume(curRect)
5140		tempRect = d7combineRect(rect, curRect)
5141		increase = d7calcRectVolume(&tempRect) - area
5142		if (increase < bestIncr) || firstTime {
5143			best = index
5144			bestArea = area
5145			bestIncr = increase
5146			firstTime = false
5147		} else if (increase == bestIncr) && (area < bestArea) {
5148			best = index
5149			bestArea = area
5150			bestIncr = increase
5151		}
5152	}
5153	return best
5154}
5155
5156// Combine two rectangles into larger one containing both
5157func d7combineRect(rectA, rectB *d7rectT) d7rectT {
5158	var newRect d7rectT
5159
5160	for index := 0; index < d7numDims; index++ {
5161		newRect.min[index] = d7fmin(rectA.min[index], rectB.min[index])
5162		newRect.max[index] = d7fmax(rectA.max[index], rectB.max[index])
5163	}
5164
5165	return newRect
5166}
5167
5168// Split a node.
5169// Divides the nodes branches and the extra one between two nodes.
5170// Old node is one of the new ones, and one really new one is created.
5171// Tries more than one method for choosing a partition, uses best result.
5172func d7splitNode(node *d7nodeT, branch *d7branchT, newNode **d7nodeT) {
5173	// Could just use local here, but member or external is faster since it is reused
5174	var localVars d7partitionVarsT
5175	parVars := &localVars
5176
5177	// Load all the branches into a buffer, initialize old node
5178	d7getBranches(node, branch, parVars)
5179
5180	// Find partition
5181	d7choosePartition(parVars, d7minNodes)
5182
5183	// Create a new node to hold (about) half of the branches
5184	*newNode = &d7nodeT{}
5185	(*newNode).level = node.level
5186
5187	// Put branches from buffer into 2 nodes according to the chosen partition
5188	node.count = 0
5189	d7loadNodes(node, *newNode, parVars)
5190}
5191
5192// Calculate the n-dimensional volume of a rectangle
5193func d7rectVolume(rect *d7rectT) float64 {
5194	var volume float64 = 1
5195	for index := 0; index < d7numDims; index++ {
5196		volume *= rect.max[index] - rect.min[index]
5197	}
5198	return volume
5199}
5200
5201// The exact volume of the bounding sphere for the given d7rectT
5202func d7rectSphericalVolume(rect *d7rectT) float64 {
5203	var sumOfSquares float64 = 0
5204	var radius float64
5205
5206	for index := 0; index < d7numDims; index++ {
5207		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
5208		sumOfSquares += halfExtent * halfExtent
5209	}
5210
5211	radius = math.Sqrt(sumOfSquares)
5212
5213	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
5214	if d7numDims == 5 {
5215		return (radius * radius * radius * radius * radius * d7unitSphereVolume)
5216	} else if d7numDims == 4 {
5217		return (radius * radius * radius * radius * d7unitSphereVolume)
5218	} else if d7numDims == 3 {
5219		return (radius * radius * radius * d7unitSphereVolume)
5220	} else if d7numDims == 2 {
5221		return (radius * radius * d7unitSphereVolume)
5222	} else {
5223		return (math.Pow(radius, d7numDims) * d7unitSphereVolume)
5224	}
5225}
5226
5227// Use one of the methods to calculate retangle volume
5228func d7calcRectVolume(rect *d7rectT) float64 {
5229	if d7useSphericalVolume {
5230		return d7rectSphericalVolume(rect) // Slower but helps certain merge cases
5231	} else { // RTREE_USE_SPHERICAL_VOLUME
5232		return d7rectVolume(rect) // Faster but can cause poor merges
5233	} // RTREE_USE_SPHERICAL_VOLUME
5234}
5235
5236// Load branch buffer with branches from full node plus the extra branch.
5237func d7getBranches(node *d7nodeT, branch *d7branchT, parVars *d7partitionVarsT) {
5238	// Load the branch buffer
5239	for index := 0; index < d7maxNodes; index++ {
5240		parVars.branchBuf[index] = node.branch[index]
5241	}
5242	parVars.branchBuf[d7maxNodes] = *branch
5243	parVars.branchCount = d7maxNodes + 1
5244
5245	// Calculate rect containing all in the set
5246	parVars.coverSplit = parVars.branchBuf[0].rect
5247	for index := 1; index < d7maxNodes+1; index++ {
5248		parVars.coverSplit = d7combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
5249	}
5250	parVars.coverSplitArea = d7calcRectVolume(&parVars.coverSplit)
5251}
5252
5253// Method #0 for choosing a partition:
5254// As the seeds for the two groups, pick the two rects that would waste the
5255// most area if covered by a single rectangle, i.e. evidently the worst pair
5256// to have in the same group.
5257// Of the remaining, one at a time is chosen to be put in one of the two groups.
5258// The one chosen is the one with the greatest difference in area expansion
5259// depending on which group - the rect most strongly attracted to one group
5260// and repelled from the other.
5261// If one group gets too full (more would force other group to violate min
5262// fill requirement) then other group gets the rest.
5263// These last are the ones that can go in either group most easily.
5264func d7choosePartition(parVars *d7partitionVarsT, minFill int) {
5265	var biggestDiff float64
5266	var group, chosen, betterGroup int
5267
5268	d7initParVars(parVars, parVars.branchCount, minFill)
5269	d7pickSeeds(parVars)
5270
5271	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
5272		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
5273		(parVars.count[1] < (parVars.total - parVars.minFill)) {
5274		biggestDiff = -1
5275		for index := 0; index < parVars.total; index++ {
5276			if d7notTaken == parVars.partition[index] {
5277				curRect := &parVars.branchBuf[index].rect
5278				rect0 := d7combineRect(curRect, &parVars.cover[0])
5279				rect1 := d7combineRect(curRect, &parVars.cover[1])
5280				growth0 := d7calcRectVolume(&rect0) - parVars.area[0]
5281				growth1 := d7calcRectVolume(&rect1) - parVars.area[1]
5282				diff := growth1 - growth0
5283				if diff >= 0 {
5284					group = 0
5285				} else {
5286					group = 1
5287					diff = -diff
5288				}
5289
5290				if diff > biggestDiff {
5291					biggestDiff = diff
5292					chosen = index
5293					betterGroup = group
5294				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
5295					chosen = index
5296					betterGroup = group
5297				}
5298			}
5299		}
5300		d7classify(chosen, betterGroup, parVars)
5301	}
5302
5303	// If one group too full, put remaining rects in the other
5304	if (parVars.count[0] + parVars.count[1]) < parVars.total {
5305		if parVars.count[0] >= parVars.total-parVars.minFill {
5306			group = 1
5307		} else {
5308			group = 0
5309		}
5310		for index := 0; index < parVars.total; index++ {
5311			if d7notTaken == parVars.partition[index] {
5312				d7classify(index, group, parVars)
5313			}
5314		}
5315	}
5316}
5317
5318// Copy branches from the buffer into two nodes according to the partition.
5319func d7loadNodes(nodeA, nodeB *d7nodeT, parVars *d7partitionVarsT) {
5320	for index := 0; index < parVars.total; index++ {
5321		targetNodeIndex := parVars.partition[index]
5322		targetNodes := []*d7nodeT{nodeA, nodeB}
5323
5324		// It is assured that d7addBranch here will not cause a node split.
5325		d7addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
5326	}
5327}
5328
5329// Initialize a d7partitionVarsT structure.
5330func d7initParVars(parVars *d7partitionVarsT, maxRects, minFill int) {
5331	parVars.count[0] = 0
5332	parVars.count[1] = 0
5333	parVars.area[0] = 0
5334	parVars.area[1] = 0
5335	parVars.total = maxRects
5336	parVars.minFill = minFill
5337	for index := 0; index < maxRects; index++ {
5338		parVars.partition[index] = d7notTaken
5339	}
5340}
5341
5342func d7pickSeeds(parVars *d7partitionVarsT) {
5343	var seed0, seed1 int
5344	var worst, waste float64
5345	var area [d7maxNodes + 1]float64
5346
5347	for index := 0; index < parVars.total; index++ {
5348		area[index] = d7calcRectVolume(&parVars.branchBuf[index].rect)
5349	}
5350
5351	worst = -parVars.coverSplitArea - 1
5352	for indexA := 0; indexA < parVars.total-1; indexA++ {
5353		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
5354			oneRect := d7combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
5355			waste = d7calcRectVolume(&oneRect) - area[indexA] - area[indexB]
5356			if waste > worst {
5357				worst = waste
5358				seed0 = indexA
5359				seed1 = indexB
5360			}
5361		}
5362	}
5363
5364	d7classify(seed0, 0, parVars)
5365	d7classify(seed1, 1, parVars)
5366}
5367
5368// Put a branch in one of the groups.
5369func d7classify(index, group int, parVars *d7partitionVarsT) {
5370	parVars.partition[index] = group
5371
5372	// Calculate combined rect
5373	if parVars.count[group] == 0 {
5374		parVars.cover[group] = parVars.branchBuf[index].rect
5375	} else {
5376		parVars.cover[group] = d7combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
5377	}
5378
5379	// Calculate volume of combined rect
5380	parVars.area[group] = d7calcRectVolume(&parVars.cover[group])
5381
5382	parVars.count[group]++
5383}
5384
5385// Delete a data rectangle from an index structure.
5386// Pass in a pointer to a d7rectT, the tid of the record, ptr to ptr to root node.
5387// Returns 1 if record not found, 0 if success.
5388// d7removeRect provides for eliminating the root.
5389func d7removeRect(rect *d7rectT, id interface{}, root **d7nodeT) bool {
5390	var reInsertList *d7listNodeT
5391
5392	if !d7removeRectRec(rect, id, *root, &reInsertList) {
5393		// Found and deleted a data item
5394		// Reinsert any branches from eliminated nodes
5395		for reInsertList != nil {
5396			tempNode := reInsertList.node
5397
5398			for index := 0; index < tempNode.count; index++ {
5399				// TODO go over this code. should I use (tempNode->m_level - 1)?
5400				d7insertRect(&tempNode.branch[index], root, tempNode.level)
5401			}
5402			reInsertList = reInsertList.next
5403		}
5404
5405		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
5406		// if with while? In case there is a whole branch of redundant roots...
5407		if (*root).count == 1 && (*root).isInternalNode() {
5408			tempNode := (*root).branch[0].child
5409			*root = tempNode
5410		}
5411		return false
5412	} else {
5413		return true
5414	}
5415}
5416
5417// Delete a rectangle from non-root part of an index structure.
5418// Called by d7removeRect.  Descends tree recursively,
5419// merges branches on the way back up.
5420// Returns 1 if record not found, 0 if success.
5421func d7removeRectRec(rect *d7rectT, id interface{}, node *d7nodeT, listNode **d7listNodeT) bool {
5422	if node.isInternalNode() { // not a leaf node
5423		for index := 0; index < node.count; index++ {
5424			if d7overlap(*rect, node.branch[index].rect) {
5425				if !d7removeRectRec(rect, id, node.branch[index].child, listNode) {
5426					if node.branch[index].child.count >= d7minNodes {
5427						// child removed, just resize parent rect
5428						node.branch[index].rect = d7nodeCover(node.branch[index].child)
5429					} else {
5430						// child removed, not enough entries in node, eliminate node
5431						d7reInsert(node.branch[index].child, listNode)
5432						d7disconnectBranch(node, index) // Must return after this call as count has changed
5433					}
5434					return false
5435				}
5436			}
5437		}
5438		return true
5439	} else { // A leaf node
5440		for index := 0; index < node.count; index++ {
5441			if node.branch[index].data == id {
5442				d7disconnectBranch(node, index) // Must return after this call as count has changed
5443				return false
5444			}
5445		}
5446		return true
5447	}
5448}
5449
5450// Decide whether two rectangles d7overlap.
5451func d7overlap(rectA, rectB d7rectT) bool {
5452	for index := 0; index < d7numDims; index++ {
5453		if rectA.min[index] > rectB.max[index] ||
5454			rectB.min[index] > rectA.max[index] {
5455			return false
5456		}
5457	}
5458	return true
5459}
5460
5461// Add a node to the reinsertion list.  All its branches will later
5462// be reinserted into the index structure.
5463func d7reInsert(node *d7nodeT, listNode **d7listNodeT) {
5464	newListNode := &d7listNodeT{}
5465	newListNode.node = node
5466	newListNode.next = *listNode
5467	*listNode = newListNode
5468}
5469
5470// d7search in an index tree or subtree for all data retangles that d7overlap the argument rectangle.
5471func d7search(node *d7nodeT, rect d7rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
5472	if node.isInternalNode() {
5473		// This is an internal node in the tree
5474		for index := 0; index < node.count; index++ {
5475			if d7overlap(rect, node.branch[index].rect) {
5476				var ok bool
5477				foundCount, ok = d7search(node.branch[index].child, rect, foundCount, resultCallback)
5478				if !ok {
5479					// The callback indicated to stop searching
5480					return foundCount, false
5481				}
5482			}
5483		}
5484	} else {
5485		// This is a leaf node
5486		for index := 0; index < node.count; index++ {
5487			if d7overlap(rect, node.branch[index].rect) {
5488				id := node.branch[index].data
5489				foundCount++
5490				if !resultCallback(id) {
5491					return foundCount, false // Don't continue searching
5492				}
5493
5494			}
5495		}
5496	}
5497	return foundCount, true // Continue searching
5498}
5499
5500func d8fmin(a, b float64) float64 {
5501	if a < b {
5502		return a
5503	}
5504	return b
5505}
5506func d8fmax(a, b float64) float64 {
5507	if a > b {
5508		return a
5509	}
5510	return b
5511}
5512
5513const (
5514	d8numDims            = 8
5515	d8maxNodes           = 8
5516	d8minNodes           = d8maxNodes / 2
5517	d8useSphericalVolume = true // Better split classification, may be slower on some systems
5518)
5519
5520var d8unitSphereVolume = []float64{
5521	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
5522	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
5523	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
5524	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
5525	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
5526	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
5527	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
5528}[d8numDims]
5529
5530type d8RTree struct {
5531	root *d8nodeT ///< Root of tree
5532}
5533
5534/// Minimal bounding rectangle (n-dimensional)
5535type d8rectT struct {
5536	min [d8numDims]float64 ///< Min dimensions of bounding box
5537	max [d8numDims]float64 ///< Max dimensions of bounding box
5538}
5539
5540/// May be data or may be another subtree
5541/// The parents level determines this.
5542/// If the parents level is 0, then this is data
5543type d8branchT struct {
5544	rect  d8rectT     ///< Bounds
5545	child *d8nodeT    ///< Child node
5546	data  interface{} ///< Data Id or Ptr
5547}
5548
5549/// d8nodeT for each branch level
5550type d8nodeT struct {
5551	count  int                   ///< Count
5552	level  int                   ///< Leaf is zero, others positive
5553	branch [d8maxNodes]d8branchT ///< Branch
5554}
5555
5556func (node *d8nodeT) isInternalNode() bool {
5557	return (node.level > 0) // Not a leaf, but a internal node
5558}
5559func (node *d8nodeT) isLeaf() bool {
5560	return (node.level == 0) // A leaf, contains data
5561}
5562
5563/// A link list of nodes for reinsertion after a delete operation
5564type d8listNodeT struct {
5565	next *d8listNodeT ///< Next in list
5566	node *d8nodeT     ///< Node
5567}
5568
5569const d8notTaken = -1 // indicates that position
5570
5571/// Variables for finding a split partition
5572type d8partitionVarsT struct {
5573	partition [d8maxNodes + 1]int
5574	total     int
5575	minFill   int
5576	count     [2]int
5577	cover     [2]d8rectT
5578	area      [2]float64
5579
5580	branchBuf      [d8maxNodes + 1]d8branchT
5581	branchCount    int
5582	coverSplit     d8rectT
5583	coverSplitArea float64
5584}
5585
5586func d8New() *d8RTree {
5587	// We only support machine word size simple data type eg. integer index or object pointer.
5588	// Since we are storing as union with non data branch
5589	return &d8RTree{
5590		root: &d8nodeT{},
5591	}
5592}
5593
5594/// Insert entry
5595/// \param a_min Min of bounding rect
5596/// \param a_max Max of bounding rect
5597/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
5598func (tr *d8RTree) Insert(min, max [d8numDims]float64, dataId interface{}) {
5599	var branch d8branchT
5600	branch.data = dataId
5601	for axis := 0; axis < d8numDims; axis++ {
5602		branch.rect.min[axis] = min[axis]
5603		branch.rect.max[axis] = max[axis]
5604	}
5605	d8insertRect(&branch, &tr.root, 0)
5606}
5607
5608/// Remove entry
5609/// \param a_min Min of bounding rect
5610/// \param a_max Max of bounding rect
5611/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
5612func (tr *d8RTree) Remove(min, max [d8numDims]float64, dataId interface{}) {
5613	var rect d8rectT
5614	for axis := 0; axis < d8numDims; axis++ {
5615		rect.min[axis] = min[axis]
5616		rect.max[axis] = max[axis]
5617	}
5618	d8removeRect(&rect, dataId, &tr.root)
5619}
5620
5621/// Find all within d8search rectangle
5622/// \param a_min Min of d8search bounding rect
5623/// \param a_max Max of d8search bounding rect
5624/// \param a_searchResult d8search result array.  Caller should set grow size. Function will reset, not append to array.
5625/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
5626/// \param a_context User context to pass as parameter to a_resultCallback
5627/// \return Returns the number of entries found
5628func (tr *d8RTree) Search(min, max [d8numDims]float64, resultCallback func(data interface{}) bool) int {
5629	var rect d8rectT
5630	for axis := 0; axis < d8numDims; axis++ {
5631		rect.min[axis] = min[axis]
5632		rect.max[axis] = max[axis]
5633	}
5634	foundCount, _ := d8search(tr.root, rect, 0, resultCallback)
5635	return foundCount
5636}
5637
5638/// Count the data elements in this container.  This is slow as no internal counter is maintained.
5639func (tr *d8RTree) Count() int {
5640	var count int
5641	d8countRec(tr.root, &count)
5642	return count
5643}
5644
5645/// Remove all entries from tree
5646func (tr *d8RTree) RemoveAll() {
5647	// Delete all existing nodes
5648	tr.root = &d8nodeT{}
5649}
5650
5651func d8countRec(node *d8nodeT, count *int) {
5652	if node.isInternalNode() { // not a leaf node
5653		for index := 0; index < node.count; index++ {
5654			d8countRec(node.branch[index].child, count)
5655		}
5656	} else { // A leaf node
5657		*count += node.count
5658	}
5659}
5660
5661// Inserts a new data rectangle into the index structure.
5662// Recursively descends tree, propagates splits back up.
5663// Returns 0 if node was not split.  Old node updated.
5664// If node was split, returns 1 and sets the pointer pointed to by
5665// new_node to point to the new node.  Old node updated to become one of two.
5666// The level argument specifies the number of steps up from the leaf
5667// level to insert; e.g. a data rectangle goes in at level = 0.
5668func d8insertRectRec(branch *d8branchT, node *d8nodeT, newNode **d8nodeT, level int) bool {
5669	// recurse until we reach the correct level for the new record. data records
5670	// will always be called with a_level == 0 (leaf)
5671	if node.level > level {
5672		// Still above level for insertion, go down tree recursively
5673		var otherNode *d8nodeT
5674		//var newBranch d8branchT
5675
5676		// find the optimal branch for this record
5677		index := d8pickBranch(&branch.rect, node)
5678
5679		// recursively insert this record into the picked branch
5680		childWasSplit := d8insertRectRec(branch, node.branch[index].child, &otherNode, level)
5681
5682		if !childWasSplit {
5683			// Child was not split. Merge the bounding box of the new record with the
5684			// existing bounding box
5685			node.branch[index].rect = d8combineRect(&branch.rect, &(node.branch[index].rect))
5686			return false
5687		} else {
5688			// Child was split. The old branches are now re-partitioned to two nodes
5689			// so we have to re-calculate the bounding boxes of each node
5690			node.branch[index].rect = d8nodeCover(node.branch[index].child)
5691			var newBranch d8branchT
5692			newBranch.child = otherNode
5693			newBranch.rect = d8nodeCover(otherNode)
5694
5695			// The old node is already a child of a_node. Now add the newly-created
5696			// node to a_node as well. a_node might be split because of that.
5697			return d8addBranch(&newBranch, node, newNode)
5698		}
5699	} else if node.level == level {
5700		// We have reached level for insertion. Add rect, split if necessary
5701		return d8addBranch(branch, node, newNode)
5702	} else {
5703		// Should never occur
5704		return false
5705	}
5706}
5707
5708// Insert a data rectangle into an index structure.
5709// d8insertRect provides for splitting the root;
5710// returns 1 if root was split, 0 if it was not.
5711// The level argument specifies the number of steps up from the leaf
5712// level to insert; e.g. a data rectangle goes in at level = 0.
5713// InsertRect2 does the recursion.
5714//
5715func d8insertRect(branch *d8branchT, root **d8nodeT, level int) bool {
5716	var newNode *d8nodeT
5717
5718	if d8insertRectRec(branch, *root, &newNode, level) { // Root split
5719
5720		// Grow tree taller and new root
5721		newRoot := &d8nodeT{}
5722		newRoot.level = (*root).level + 1
5723
5724		var newBranch d8branchT
5725
5726		// add old root node as a child of the new root
5727		newBranch.rect = d8nodeCover(*root)
5728		newBranch.child = *root
5729		d8addBranch(&newBranch, newRoot, nil)
5730
5731		// add the split node as a child of the new root
5732		newBranch.rect = d8nodeCover(newNode)
5733		newBranch.child = newNode
5734		d8addBranch(&newBranch, newRoot, nil)
5735
5736		// set the new root as the root node
5737		*root = newRoot
5738
5739		return true
5740	}
5741	return false
5742}
5743
5744// Find the smallest rectangle that includes all rectangles in branches of a node.
5745func d8nodeCover(node *d8nodeT) d8rectT {
5746	rect := node.branch[0].rect
5747	for index := 1; index < node.count; index++ {
5748		rect = d8combineRect(&rect, &(node.branch[index].rect))
5749	}
5750	return rect
5751}
5752
5753// Add a branch to a node.  Split the node if necessary.
5754// Returns 0 if node not split.  Old node updated.
5755// Returns 1 if node split, sets *new_node to address of new node.
5756// Old node updated, becomes one of two.
5757func d8addBranch(branch *d8branchT, node *d8nodeT, newNode **d8nodeT) bool {
5758	if node.count < d8maxNodes { // Split won't be necessary
5759		node.branch[node.count] = *branch
5760		node.count++
5761		return false
5762	} else {
5763		d8splitNode(node, branch, newNode)
5764		return true
5765	}
5766}
5767
5768// Disconnect a dependent node.
5769// Caller must return (or stop using iteration index) after this as count has changed
5770func d8disconnectBranch(node *d8nodeT, index int) {
5771	// Remove element by swapping with the last element to prevent gaps in array
5772	node.branch[index] = node.branch[node.count-1]
5773	node.branch[node.count-1].data = nil
5774	node.branch[node.count-1].child = nil
5775	node.count--
5776}
5777
5778// Pick a branch.  Pick the one that will need the smallest increase
5779// in area to accomodate the new rectangle.  This will result in the
5780// least total area for the covering rectangles in the current node.
5781// In case of a tie, pick the one which was smaller before, to get
5782// the best resolution when searching.
5783func d8pickBranch(rect *d8rectT, node *d8nodeT) int {
5784	var firstTime bool = true
5785	var increase float64
5786	var bestIncr float64 = -1
5787	var area float64
5788	var bestArea float64
5789	var best int
5790	var tempRect d8rectT
5791
5792	for index := 0; index < node.count; index++ {
5793		curRect := &node.branch[index].rect
5794		area = d8calcRectVolume(curRect)
5795		tempRect = d8combineRect(rect, curRect)
5796		increase = d8calcRectVolume(&tempRect) - area
5797		if (increase < bestIncr) || firstTime {
5798			best = index
5799			bestArea = area
5800			bestIncr = increase
5801			firstTime = false
5802		} else if (increase == bestIncr) && (area < bestArea) {
5803			best = index
5804			bestArea = area
5805			bestIncr = increase
5806		}
5807	}
5808	return best
5809}
5810
5811// Combine two rectangles into larger one containing both
5812func d8combineRect(rectA, rectB *d8rectT) d8rectT {
5813	var newRect d8rectT
5814
5815	for index := 0; index < d8numDims; index++ {
5816		newRect.min[index] = d8fmin(rectA.min[index], rectB.min[index])
5817		newRect.max[index] = d8fmax(rectA.max[index], rectB.max[index])
5818	}
5819
5820	return newRect
5821}
5822
5823// Split a node.
5824// Divides the nodes branches and the extra one between two nodes.
5825// Old node is one of the new ones, and one really new one is created.
5826// Tries more than one method for choosing a partition, uses best result.
5827func d8splitNode(node *d8nodeT, branch *d8branchT, newNode **d8nodeT) {
5828	// Could just use local here, but member or external is faster since it is reused
5829	var localVars d8partitionVarsT
5830	parVars := &localVars
5831
5832	// Load all the branches into a buffer, initialize old node
5833	d8getBranches(node, branch, parVars)
5834
5835	// Find partition
5836	d8choosePartition(parVars, d8minNodes)
5837
5838	// Create a new node to hold (about) half of the branches
5839	*newNode = &d8nodeT{}
5840	(*newNode).level = node.level
5841
5842	// Put branches from buffer into 2 nodes according to the chosen partition
5843	node.count = 0
5844	d8loadNodes(node, *newNode, parVars)
5845}
5846
5847// Calculate the n-dimensional volume of a rectangle
5848func d8rectVolume(rect *d8rectT) float64 {
5849	var volume float64 = 1
5850	for index := 0; index < d8numDims; index++ {
5851		volume *= rect.max[index] - rect.min[index]
5852	}
5853	return volume
5854}
5855
5856// The exact volume of the bounding sphere for the given d8rectT
5857func d8rectSphericalVolume(rect *d8rectT) float64 {
5858	var sumOfSquares float64 = 0
5859	var radius float64
5860
5861	for index := 0; index < d8numDims; index++ {
5862		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
5863		sumOfSquares += halfExtent * halfExtent
5864	}
5865
5866	radius = math.Sqrt(sumOfSquares)
5867
5868	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
5869	if d8numDims == 5 {
5870		return (radius * radius * radius * radius * radius * d8unitSphereVolume)
5871	} else if d8numDims == 4 {
5872		return (radius * radius * radius * radius * d8unitSphereVolume)
5873	} else if d8numDims == 3 {
5874		return (radius * radius * radius * d8unitSphereVolume)
5875	} else if d8numDims == 2 {
5876		return (radius * radius * d8unitSphereVolume)
5877	} else {
5878		return (math.Pow(radius, d8numDims) * d8unitSphereVolume)
5879	}
5880}
5881
5882// Use one of the methods to calculate retangle volume
5883func d8calcRectVolume(rect *d8rectT) float64 {
5884	if d8useSphericalVolume {
5885		return d8rectSphericalVolume(rect) // Slower but helps certain merge cases
5886	} else { // RTREE_USE_SPHERICAL_VOLUME
5887		return d8rectVolume(rect) // Faster but can cause poor merges
5888	} // RTREE_USE_SPHERICAL_VOLUME
5889}
5890
5891// Load branch buffer with branches from full node plus the extra branch.
5892func d8getBranches(node *d8nodeT, branch *d8branchT, parVars *d8partitionVarsT) {
5893	// Load the branch buffer
5894	for index := 0; index < d8maxNodes; index++ {
5895		parVars.branchBuf[index] = node.branch[index]
5896	}
5897	parVars.branchBuf[d8maxNodes] = *branch
5898	parVars.branchCount = d8maxNodes + 1
5899
5900	// Calculate rect containing all in the set
5901	parVars.coverSplit = parVars.branchBuf[0].rect
5902	for index := 1; index < d8maxNodes+1; index++ {
5903		parVars.coverSplit = d8combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
5904	}
5905	parVars.coverSplitArea = d8calcRectVolume(&parVars.coverSplit)
5906}
5907
5908// Method #0 for choosing a partition:
5909// As the seeds for the two groups, pick the two rects that would waste the
5910// most area if covered by a single rectangle, i.e. evidently the worst pair
5911// to have in the same group.
5912// Of the remaining, one at a time is chosen to be put in one of the two groups.
5913// The one chosen is the one with the greatest difference in area expansion
5914// depending on which group - the rect most strongly attracted to one group
5915// and repelled from the other.
5916// If one group gets too full (more would force other group to violate min
5917// fill requirement) then other group gets the rest.
5918// These last are the ones that can go in either group most easily.
5919func d8choosePartition(parVars *d8partitionVarsT, minFill int) {
5920	var biggestDiff float64
5921	var group, chosen, betterGroup int
5922
5923	d8initParVars(parVars, parVars.branchCount, minFill)
5924	d8pickSeeds(parVars)
5925
5926	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
5927		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
5928		(parVars.count[1] < (parVars.total - parVars.minFill)) {
5929		biggestDiff = -1
5930		for index := 0; index < parVars.total; index++ {
5931			if d8notTaken == parVars.partition[index] {
5932				curRect := &parVars.branchBuf[index].rect
5933				rect0 := d8combineRect(curRect, &parVars.cover[0])
5934				rect1 := d8combineRect(curRect, &parVars.cover[1])
5935				growth0 := d8calcRectVolume(&rect0) - parVars.area[0]
5936				growth1 := d8calcRectVolume(&rect1) - parVars.area[1]
5937				diff := growth1 - growth0
5938				if diff >= 0 {
5939					group = 0
5940				} else {
5941					group = 1
5942					diff = -diff
5943				}
5944
5945				if diff > biggestDiff {
5946					biggestDiff = diff
5947					chosen = index
5948					betterGroup = group
5949				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
5950					chosen = index
5951					betterGroup = group
5952				}
5953			}
5954		}
5955		d8classify(chosen, betterGroup, parVars)
5956	}
5957
5958	// If one group too full, put remaining rects in the other
5959	if (parVars.count[0] + parVars.count[1]) < parVars.total {
5960		if parVars.count[0] >= parVars.total-parVars.minFill {
5961			group = 1
5962		} else {
5963			group = 0
5964		}
5965		for index := 0; index < parVars.total; index++ {
5966			if d8notTaken == parVars.partition[index] {
5967				d8classify(index, group, parVars)
5968			}
5969		}
5970	}
5971}
5972
5973// Copy branches from the buffer into two nodes according to the partition.
5974func d8loadNodes(nodeA, nodeB *d8nodeT, parVars *d8partitionVarsT) {
5975	for index := 0; index < parVars.total; index++ {
5976		targetNodeIndex := parVars.partition[index]
5977		targetNodes := []*d8nodeT{nodeA, nodeB}
5978
5979		// It is assured that d8addBranch here will not cause a node split.
5980		d8addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
5981	}
5982}
5983
5984// Initialize a d8partitionVarsT structure.
5985func d8initParVars(parVars *d8partitionVarsT, maxRects, minFill int) {
5986	parVars.count[0] = 0
5987	parVars.count[1] = 0
5988	parVars.area[0] = 0
5989	parVars.area[1] = 0
5990	parVars.total = maxRects
5991	parVars.minFill = minFill
5992	for index := 0; index < maxRects; index++ {
5993		parVars.partition[index] = d8notTaken
5994	}
5995}
5996
5997func d8pickSeeds(parVars *d8partitionVarsT) {
5998	var seed0, seed1 int
5999	var worst, waste float64
6000	var area [d8maxNodes + 1]float64
6001
6002	for index := 0; index < parVars.total; index++ {
6003		area[index] = d8calcRectVolume(&parVars.branchBuf[index].rect)
6004	}
6005
6006	worst = -parVars.coverSplitArea - 1
6007	for indexA := 0; indexA < parVars.total-1; indexA++ {
6008		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
6009			oneRect := d8combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
6010			waste = d8calcRectVolume(&oneRect) - area[indexA] - area[indexB]
6011			if waste > worst {
6012				worst = waste
6013				seed0 = indexA
6014				seed1 = indexB
6015			}
6016		}
6017	}
6018
6019	d8classify(seed0, 0, parVars)
6020	d8classify(seed1, 1, parVars)
6021}
6022
6023// Put a branch in one of the groups.
6024func d8classify(index, group int, parVars *d8partitionVarsT) {
6025	parVars.partition[index] = group
6026
6027	// Calculate combined rect
6028	if parVars.count[group] == 0 {
6029		parVars.cover[group] = parVars.branchBuf[index].rect
6030	} else {
6031		parVars.cover[group] = d8combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
6032	}
6033
6034	// Calculate volume of combined rect
6035	parVars.area[group] = d8calcRectVolume(&parVars.cover[group])
6036
6037	parVars.count[group]++
6038}
6039
6040// Delete a data rectangle from an index structure.
6041// Pass in a pointer to a d8rectT, the tid of the record, ptr to ptr to root node.
6042// Returns 1 if record not found, 0 if success.
6043// d8removeRect provides for eliminating the root.
6044func d8removeRect(rect *d8rectT, id interface{}, root **d8nodeT) bool {
6045	var reInsertList *d8listNodeT
6046
6047	if !d8removeRectRec(rect, id, *root, &reInsertList) {
6048		// Found and deleted a data item
6049		// Reinsert any branches from eliminated nodes
6050		for reInsertList != nil {
6051			tempNode := reInsertList.node
6052
6053			for index := 0; index < tempNode.count; index++ {
6054				// TODO go over this code. should I use (tempNode->m_level - 1)?
6055				d8insertRect(&tempNode.branch[index], root, tempNode.level)
6056			}
6057			reInsertList = reInsertList.next
6058		}
6059
6060		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
6061		// if with while? In case there is a whole branch of redundant roots...
6062		if (*root).count == 1 && (*root).isInternalNode() {
6063			tempNode := (*root).branch[0].child
6064			*root = tempNode
6065		}
6066		return false
6067	} else {
6068		return true
6069	}
6070}
6071
6072// Delete a rectangle from non-root part of an index structure.
6073// Called by d8removeRect.  Descends tree recursively,
6074// merges branches on the way back up.
6075// Returns 1 if record not found, 0 if success.
6076func d8removeRectRec(rect *d8rectT, id interface{}, node *d8nodeT, listNode **d8listNodeT) bool {
6077	if node.isInternalNode() { // not a leaf node
6078		for index := 0; index < node.count; index++ {
6079			if d8overlap(*rect, node.branch[index].rect) {
6080				if !d8removeRectRec(rect, id, node.branch[index].child, listNode) {
6081					if node.branch[index].child.count >= d8minNodes {
6082						// child removed, just resize parent rect
6083						node.branch[index].rect = d8nodeCover(node.branch[index].child)
6084					} else {
6085						// child removed, not enough entries in node, eliminate node
6086						d8reInsert(node.branch[index].child, listNode)
6087						d8disconnectBranch(node, index) // Must return after this call as count has changed
6088					}
6089					return false
6090				}
6091			}
6092		}
6093		return true
6094	} else { // A leaf node
6095		for index := 0; index < node.count; index++ {
6096			if node.branch[index].data == id {
6097				d8disconnectBranch(node, index) // Must return after this call as count has changed
6098				return false
6099			}
6100		}
6101		return true
6102	}
6103}
6104
6105// Decide whether two rectangles d8overlap.
6106func d8overlap(rectA, rectB d8rectT) bool {
6107	for index := 0; index < d8numDims; index++ {
6108		if rectA.min[index] > rectB.max[index] ||
6109			rectB.min[index] > rectA.max[index] {
6110			return false
6111		}
6112	}
6113	return true
6114}
6115
6116// Add a node to the reinsertion list.  All its branches will later
6117// be reinserted into the index structure.
6118func d8reInsert(node *d8nodeT, listNode **d8listNodeT) {
6119	newListNode := &d8listNodeT{}
6120	newListNode.node = node
6121	newListNode.next = *listNode
6122	*listNode = newListNode
6123}
6124
6125// d8search in an index tree or subtree for all data retangles that d8overlap the argument rectangle.
6126func d8search(node *d8nodeT, rect d8rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
6127	if node.isInternalNode() {
6128		// This is an internal node in the tree
6129		for index := 0; index < node.count; index++ {
6130			if d8overlap(rect, node.branch[index].rect) {
6131				var ok bool
6132				foundCount, ok = d8search(node.branch[index].child, rect, foundCount, resultCallback)
6133				if !ok {
6134					// The callback indicated to stop searching
6135					return foundCount, false
6136				}
6137			}
6138		}
6139	} else {
6140		// This is a leaf node
6141		for index := 0; index < node.count; index++ {
6142			if d8overlap(rect, node.branch[index].rect) {
6143				id := node.branch[index].data
6144				foundCount++
6145				if !resultCallback(id) {
6146					return foundCount, false // Don't continue searching
6147				}
6148
6149			}
6150		}
6151	}
6152	return foundCount, true // Continue searching
6153}
6154
6155func d9fmin(a, b float64) float64 {
6156	if a < b {
6157		return a
6158	}
6159	return b
6160}
6161func d9fmax(a, b float64) float64 {
6162	if a > b {
6163		return a
6164	}
6165	return b
6166}
6167
6168const (
6169	d9numDims            = 9
6170	d9maxNodes           = 8
6171	d9minNodes           = d9maxNodes / 2
6172	d9useSphericalVolume = true // Better split classification, may be slower on some systems
6173)
6174
6175var d9unitSphereVolume = []float64{
6176	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
6177	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
6178	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
6179	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
6180	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
6181	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
6182	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
6183}[d9numDims]
6184
6185type d9RTree struct {
6186	root *d9nodeT ///< Root of tree
6187}
6188
6189/// Minimal bounding rectangle (n-dimensional)
6190type d9rectT struct {
6191	min [d9numDims]float64 ///< Min dimensions of bounding box
6192	max [d9numDims]float64 ///< Max dimensions of bounding box
6193}
6194
6195/// May be data or may be another subtree
6196/// The parents level determines this.
6197/// If the parents level is 0, then this is data
6198type d9branchT struct {
6199	rect  d9rectT     ///< Bounds
6200	child *d9nodeT    ///< Child node
6201	data  interface{} ///< Data Id or Ptr
6202}
6203
6204/// d9nodeT for each branch level
6205type d9nodeT struct {
6206	count  int                   ///< Count
6207	level  int                   ///< Leaf is zero, others positive
6208	branch [d9maxNodes]d9branchT ///< Branch
6209}
6210
6211func (node *d9nodeT) isInternalNode() bool {
6212	return (node.level > 0) // Not a leaf, but a internal node
6213}
6214func (node *d9nodeT) isLeaf() bool {
6215	return (node.level == 0) // A leaf, contains data
6216}
6217
6218/// A link list of nodes for reinsertion after a delete operation
6219type d9listNodeT struct {
6220	next *d9listNodeT ///< Next in list
6221	node *d9nodeT     ///< Node
6222}
6223
6224const d9notTaken = -1 // indicates that position
6225
6226/// Variables for finding a split partition
6227type d9partitionVarsT struct {
6228	partition [d9maxNodes + 1]int
6229	total     int
6230	minFill   int
6231	count     [2]int
6232	cover     [2]d9rectT
6233	area      [2]float64
6234
6235	branchBuf      [d9maxNodes + 1]d9branchT
6236	branchCount    int
6237	coverSplit     d9rectT
6238	coverSplitArea float64
6239}
6240
6241func d9New() *d9RTree {
6242	// We only support machine word size simple data type eg. integer index or object pointer.
6243	// Since we are storing as union with non data branch
6244	return &d9RTree{
6245		root: &d9nodeT{},
6246	}
6247}
6248
6249/// Insert entry
6250/// \param a_min Min of bounding rect
6251/// \param a_max Max of bounding rect
6252/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
6253func (tr *d9RTree) Insert(min, max [d9numDims]float64, dataId interface{}) {
6254	var branch d9branchT
6255	branch.data = dataId
6256	for axis := 0; axis < d9numDims; axis++ {
6257		branch.rect.min[axis] = min[axis]
6258		branch.rect.max[axis] = max[axis]
6259	}
6260	d9insertRect(&branch, &tr.root, 0)
6261}
6262
6263/// Remove entry
6264/// \param a_min Min of bounding rect
6265/// \param a_max Max of bounding rect
6266/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
6267func (tr *d9RTree) Remove(min, max [d9numDims]float64, dataId interface{}) {
6268	var rect d9rectT
6269	for axis := 0; axis < d9numDims; axis++ {
6270		rect.min[axis] = min[axis]
6271		rect.max[axis] = max[axis]
6272	}
6273	d9removeRect(&rect, dataId, &tr.root)
6274}
6275
6276/// Find all within d9search rectangle
6277/// \param a_min Min of d9search bounding rect
6278/// \param a_max Max of d9search bounding rect
6279/// \param a_searchResult d9search result array.  Caller should set grow size. Function will reset, not append to array.
6280/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
6281/// \param a_context User context to pass as parameter to a_resultCallback
6282/// \return Returns the number of entries found
6283func (tr *d9RTree) Search(min, max [d9numDims]float64, resultCallback func(data interface{}) bool) int {
6284	var rect d9rectT
6285	for axis := 0; axis < d9numDims; axis++ {
6286		rect.min[axis] = min[axis]
6287		rect.max[axis] = max[axis]
6288	}
6289	foundCount, _ := d9search(tr.root, rect, 0, resultCallback)
6290	return foundCount
6291}
6292
6293/// Count the data elements in this container.  This is slow as no internal counter is maintained.
6294func (tr *d9RTree) Count() int {
6295	var count int
6296	d9countRec(tr.root, &count)
6297	return count
6298}
6299
6300/// Remove all entries from tree
6301func (tr *d9RTree) RemoveAll() {
6302	// Delete all existing nodes
6303	tr.root = &d9nodeT{}
6304}
6305
6306func d9countRec(node *d9nodeT, count *int) {
6307	if node.isInternalNode() { // not a leaf node
6308		for index := 0; index < node.count; index++ {
6309			d9countRec(node.branch[index].child, count)
6310		}
6311	} else { // A leaf node
6312		*count += node.count
6313	}
6314}
6315
6316// Inserts a new data rectangle into the index structure.
6317// Recursively descends tree, propagates splits back up.
6318// Returns 0 if node was not split.  Old node updated.
6319// If node was split, returns 1 and sets the pointer pointed to by
6320// new_node to point to the new node.  Old node updated to become one of two.
6321// The level argument specifies the number of steps up from the leaf
6322// level to insert; e.g. a data rectangle goes in at level = 0.
6323func d9insertRectRec(branch *d9branchT, node *d9nodeT, newNode **d9nodeT, level int) bool {
6324	// recurse until we reach the correct level for the new record. data records
6325	// will always be called with a_level == 0 (leaf)
6326	if node.level > level {
6327		// Still above level for insertion, go down tree recursively
6328		var otherNode *d9nodeT
6329		//var newBranch d9branchT
6330
6331		// find the optimal branch for this record
6332		index := d9pickBranch(&branch.rect, node)
6333
6334		// recursively insert this record into the picked branch
6335		childWasSplit := d9insertRectRec(branch, node.branch[index].child, &otherNode, level)
6336
6337		if !childWasSplit {
6338			// Child was not split. Merge the bounding box of the new record with the
6339			// existing bounding box
6340			node.branch[index].rect = d9combineRect(&branch.rect, &(node.branch[index].rect))
6341			return false
6342		} else {
6343			// Child was split. The old branches are now re-partitioned to two nodes
6344			// so we have to re-calculate the bounding boxes of each node
6345			node.branch[index].rect = d9nodeCover(node.branch[index].child)
6346			var newBranch d9branchT
6347			newBranch.child = otherNode
6348			newBranch.rect = d9nodeCover(otherNode)
6349
6350			// The old node is already a child of a_node. Now add the newly-created
6351			// node to a_node as well. a_node might be split because of that.
6352			return d9addBranch(&newBranch, node, newNode)
6353		}
6354	} else if node.level == level {
6355		// We have reached level for insertion. Add rect, split if necessary
6356		return d9addBranch(branch, node, newNode)
6357	} else {
6358		// Should never occur
6359		return false
6360	}
6361}
6362
6363// Insert a data rectangle into an index structure.
6364// d9insertRect provides for splitting the root;
6365// returns 1 if root was split, 0 if it was not.
6366// The level argument specifies the number of steps up from the leaf
6367// level to insert; e.g. a data rectangle goes in at level = 0.
6368// InsertRect2 does the recursion.
6369//
6370func d9insertRect(branch *d9branchT, root **d9nodeT, level int) bool {
6371	var newNode *d9nodeT
6372
6373	if d9insertRectRec(branch, *root, &newNode, level) { // Root split
6374
6375		// Grow tree taller and new root
6376		newRoot := &d9nodeT{}
6377		newRoot.level = (*root).level + 1
6378
6379		var newBranch d9branchT
6380
6381		// add old root node as a child of the new root
6382		newBranch.rect = d9nodeCover(*root)
6383		newBranch.child = *root
6384		d9addBranch(&newBranch, newRoot, nil)
6385
6386		// add the split node as a child of the new root
6387		newBranch.rect = d9nodeCover(newNode)
6388		newBranch.child = newNode
6389		d9addBranch(&newBranch, newRoot, nil)
6390
6391		// set the new root as the root node
6392		*root = newRoot
6393
6394		return true
6395	}
6396	return false
6397}
6398
6399// Find the smallest rectangle that includes all rectangles in branches of a node.
6400func d9nodeCover(node *d9nodeT) d9rectT {
6401	rect := node.branch[0].rect
6402	for index := 1; index < node.count; index++ {
6403		rect = d9combineRect(&rect, &(node.branch[index].rect))
6404	}
6405	return rect
6406}
6407
6408// Add a branch to a node.  Split the node if necessary.
6409// Returns 0 if node not split.  Old node updated.
6410// Returns 1 if node split, sets *new_node to address of new node.
6411// Old node updated, becomes one of two.
6412func d9addBranch(branch *d9branchT, node *d9nodeT, newNode **d9nodeT) bool {
6413	if node.count < d9maxNodes { // Split won't be necessary
6414		node.branch[node.count] = *branch
6415		node.count++
6416		return false
6417	} else {
6418		d9splitNode(node, branch, newNode)
6419		return true
6420	}
6421}
6422
6423// Disconnect a dependent node.
6424// Caller must return (or stop using iteration index) after this as count has changed
6425func d9disconnectBranch(node *d9nodeT, index int) {
6426	// Remove element by swapping with the last element to prevent gaps in array
6427	node.branch[index] = node.branch[node.count-1]
6428	node.branch[node.count-1].data = nil
6429	node.branch[node.count-1].child = nil
6430	node.count--
6431}
6432
6433// Pick a branch.  Pick the one that will need the smallest increase
6434// in area to accomodate the new rectangle.  This will result in the
6435// least total area for the covering rectangles in the current node.
6436// In case of a tie, pick the one which was smaller before, to get
6437// the best resolution when searching.
6438func d9pickBranch(rect *d9rectT, node *d9nodeT) int {
6439	var firstTime bool = true
6440	var increase float64
6441	var bestIncr float64 = -1
6442	var area float64
6443	var bestArea float64
6444	var best int
6445	var tempRect d9rectT
6446
6447	for index := 0; index < node.count; index++ {
6448		curRect := &node.branch[index].rect
6449		area = d9calcRectVolume(curRect)
6450		tempRect = d9combineRect(rect, curRect)
6451		increase = d9calcRectVolume(&tempRect) - area
6452		if (increase < bestIncr) || firstTime {
6453			best = index
6454			bestArea = area
6455			bestIncr = increase
6456			firstTime = false
6457		} else if (increase == bestIncr) && (area < bestArea) {
6458			best = index
6459			bestArea = area
6460			bestIncr = increase
6461		}
6462	}
6463	return best
6464}
6465
6466// Combine two rectangles into larger one containing both
6467func d9combineRect(rectA, rectB *d9rectT) d9rectT {
6468	var newRect d9rectT
6469
6470	for index := 0; index < d9numDims; index++ {
6471		newRect.min[index] = d9fmin(rectA.min[index], rectB.min[index])
6472		newRect.max[index] = d9fmax(rectA.max[index], rectB.max[index])
6473	}
6474
6475	return newRect
6476}
6477
6478// Split a node.
6479// Divides the nodes branches and the extra one between two nodes.
6480// Old node is one of the new ones, and one really new one is created.
6481// Tries more than one method for choosing a partition, uses best result.
6482func d9splitNode(node *d9nodeT, branch *d9branchT, newNode **d9nodeT) {
6483	// Could just use local here, but member or external is faster since it is reused
6484	var localVars d9partitionVarsT
6485	parVars := &localVars
6486
6487	// Load all the branches into a buffer, initialize old node
6488	d9getBranches(node, branch, parVars)
6489
6490	// Find partition
6491	d9choosePartition(parVars, d9minNodes)
6492
6493	// Create a new node to hold (about) half of the branches
6494	*newNode = &d9nodeT{}
6495	(*newNode).level = node.level
6496
6497	// Put branches from buffer into 2 nodes according to the chosen partition
6498	node.count = 0
6499	d9loadNodes(node, *newNode, parVars)
6500}
6501
6502// Calculate the n-dimensional volume of a rectangle
6503func d9rectVolume(rect *d9rectT) float64 {
6504	var volume float64 = 1
6505	for index := 0; index < d9numDims; index++ {
6506		volume *= rect.max[index] - rect.min[index]
6507	}
6508	return volume
6509}
6510
6511// The exact volume of the bounding sphere for the given d9rectT
6512func d9rectSphericalVolume(rect *d9rectT) float64 {
6513	var sumOfSquares float64 = 0
6514	var radius float64
6515
6516	for index := 0; index < d9numDims; index++ {
6517		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
6518		sumOfSquares += halfExtent * halfExtent
6519	}
6520
6521	radius = math.Sqrt(sumOfSquares)
6522
6523	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
6524	if d9numDims == 5 {
6525		return (radius * radius * radius * radius * radius * d9unitSphereVolume)
6526	} else if d9numDims == 4 {
6527		return (radius * radius * radius * radius * d9unitSphereVolume)
6528	} else if d9numDims == 3 {
6529		return (radius * radius * radius * d9unitSphereVolume)
6530	} else if d9numDims == 2 {
6531		return (radius * radius * d9unitSphereVolume)
6532	} else {
6533		return (math.Pow(radius, d9numDims) * d9unitSphereVolume)
6534	}
6535}
6536
6537// Use one of the methods to calculate retangle volume
6538func d9calcRectVolume(rect *d9rectT) float64 {
6539	if d9useSphericalVolume {
6540		return d9rectSphericalVolume(rect) // Slower but helps certain merge cases
6541	} else { // RTREE_USE_SPHERICAL_VOLUME
6542		return d9rectVolume(rect) // Faster but can cause poor merges
6543	} // RTREE_USE_SPHERICAL_VOLUME
6544}
6545
6546// Load branch buffer with branches from full node plus the extra branch.
6547func d9getBranches(node *d9nodeT, branch *d9branchT, parVars *d9partitionVarsT) {
6548	// Load the branch buffer
6549	for index := 0; index < d9maxNodes; index++ {
6550		parVars.branchBuf[index] = node.branch[index]
6551	}
6552	parVars.branchBuf[d9maxNodes] = *branch
6553	parVars.branchCount = d9maxNodes + 1
6554
6555	// Calculate rect containing all in the set
6556	parVars.coverSplit = parVars.branchBuf[0].rect
6557	for index := 1; index < d9maxNodes+1; index++ {
6558		parVars.coverSplit = d9combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
6559	}
6560	parVars.coverSplitArea = d9calcRectVolume(&parVars.coverSplit)
6561}
6562
6563// Method #0 for choosing a partition:
6564// As the seeds for the two groups, pick the two rects that would waste the
6565// most area if covered by a single rectangle, i.e. evidently the worst pair
6566// to have in the same group.
6567// Of the remaining, one at a time is chosen to be put in one of the two groups.
6568// The one chosen is the one with the greatest difference in area expansion
6569// depending on which group - the rect most strongly attracted to one group
6570// and repelled from the other.
6571// If one group gets too full (more would force other group to violate min
6572// fill requirement) then other group gets the rest.
6573// These last are the ones that can go in either group most easily.
6574func d9choosePartition(parVars *d9partitionVarsT, minFill int) {
6575	var biggestDiff float64
6576	var group, chosen, betterGroup int
6577
6578	d9initParVars(parVars, parVars.branchCount, minFill)
6579	d9pickSeeds(parVars)
6580
6581	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
6582		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
6583		(parVars.count[1] < (parVars.total - parVars.minFill)) {
6584		biggestDiff = -1
6585		for index := 0; index < parVars.total; index++ {
6586			if d9notTaken == parVars.partition[index] {
6587				curRect := &parVars.branchBuf[index].rect
6588				rect0 := d9combineRect(curRect, &parVars.cover[0])
6589				rect1 := d9combineRect(curRect, &parVars.cover[1])
6590				growth0 := d9calcRectVolume(&rect0) - parVars.area[0]
6591				growth1 := d9calcRectVolume(&rect1) - parVars.area[1]
6592				diff := growth1 - growth0
6593				if diff >= 0 {
6594					group = 0
6595				} else {
6596					group = 1
6597					diff = -diff
6598				}
6599
6600				if diff > biggestDiff {
6601					biggestDiff = diff
6602					chosen = index
6603					betterGroup = group
6604				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
6605					chosen = index
6606					betterGroup = group
6607				}
6608			}
6609		}
6610		d9classify(chosen, betterGroup, parVars)
6611	}
6612
6613	// If one group too full, put remaining rects in the other
6614	if (parVars.count[0] + parVars.count[1]) < parVars.total {
6615		if parVars.count[0] >= parVars.total-parVars.minFill {
6616			group = 1
6617		} else {
6618			group = 0
6619		}
6620		for index := 0; index < parVars.total; index++ {
6621			if d9notTaken == parVars.partition[index] {
6622				d9classify(index, group, parVars)
6623			}
6624		}
6625	}
6626}
6627
6628// Copy branches from the buffer into two nodes according to the partition.
6629func d9loadNodes(nodeA, nodeB *d9nodeT, parVars *d9partitionVarsT) {
6630	for index := 0; index < parVars.total; index++ {
6631		targetNodeIndex := parVars.partition[index]
6632		targetNodes := []*d9nodeT{nodeA, nodeB}
6633
6634		// It is assured that d9addBranch here will not cause a node split.
6635		d9addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
6636	}
6637}
6638
6639// Initialize a d9partitionVarsT structure.
6640func d9initParVars(parVars *d9partitionVarsT, maxRects, minFill int) {
6641	parVars.count[0] = 0
6642	parVars.count[1] = 0
6643	parVars.area[0] = 0
6644	parVars.area[1] = 0
6645	parVars.total = maxRects
6646	parVars.minFill = minFill
6647	for index := 0; index < maxRects; index++ {
6648		parVars.partition[index] = d9notTaken
6649	}
6650}
6651
6652func d9pickSeeds(parVars *d9partitionVarsT) {
6653	var seed0, seed1 int
6654	var worst, waste float64
6655	var area [d9maxNodes + 1]float64
6656
6657	for index := 0; index < parVars.total; index++ {
6658		area[index] = d9calcRectVolume(&parVars.branchBuf[index].rect)
6659	}
6660
6661	worst = -parVars.coverSplitArea - 1
6662	for indexA := 0; indexA < parVars.total-1; indexA++ {
6663		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
6664			oneRect := d9combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
6665			waste = d9calcRectVolume(&oneRect) - area[indexA] - area[indexB]
6666			if waste > worst {
6667				worst = waste
6668				seed0 = indexA
6669				seed1 = indexB
6670			}
6671		}
6672	}
6673
6674	d9classify(seed0, 0, parVars)
6675	d9classify(seed1, 1, parVars)
6676}
6677
6678// Put a branch in one of the groups.
6679func d9classify(index, group int, parVars *d9partitionVarsT) {
6680	parVars.partition[index] = group
6681
6682	// Calculate combined rect
6683	if parVars.count[group] == 0 {
6684		parVars.cover[group] = parVars.branchBuf[index].rect
6685	} else {
6686		parVars.cover[group] = d9combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
6687	}
6688
6689	// Calculate volume of combined rect
6690	parVars.area[group] = d9calcRectVolume(&parVars.cover[group])
6691
6692	parVars.count[group]++
6693}
6694
6695// Delete a data rectangle from an index structure.
6696// Pass in a pointer to a d9rectT, the tid of the record, ptr to ptr to root node.
6697// Returns 1 if record not found, 0 if success.
6698// d9removeRect provides for eliminating the root.
6699func d9removeRect(rect *d9rectT, id interface{}, root **d9nodeT) bool {
6700	var reInsertList *d9listNodeT
6701
6702	if !d9removeRectRec(rect, id, *root, &reInsertList) {
6703		// Found and deleted a data item
6704		// Reinsert any branches from eliminated nodes
6705		for reInsertList != nil {
6706			tempNode := reInsertList.node
6707
6708			for index := 0; index < tempNode.count; index++ {
6709				// TODO go over this code. should I use (tempNode->m_level - 1)?
6710				d9insertRect(&tempNode.branch[index], root, tempNode.level)
6711			}
6712			reInsertList = reInsertList.next
6713		}
6714
6715		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
6716		// if with while? In case there is a whole branch of redundant roots...
6717		if (*root).count == 1 && (*root).isInternalNode() {
6718			tempNode := (*root).branch[0].child
6719			*root = tempNode
6720		}
6721		return false
6722	} else {
6723		return true
6724	}
6725}
6726
6727// Delete a rectangle from non-root part of an index structure.
6728// Called by d9removeRect.  Descends tree recursively,
6729// merges branches on the way back up.
6730// Returns 1 if record not found, 0 if success.
6731func d9removeRectRec(rect *d9rectT, id interface{}, node *d9nodeT, listNode **d9listNodeT) bool {
6732	if node.isInternalNode() { // not a leaf node
6733		for index := 0; index < node.count; index++ {
6734			if d9overlap(*rect, node.branch[index].rect) {
6735				if !d9removeRectRec(rect, id, node.branch[index].child, listNode) {
6736					if node.branch[index].child.count >= d9minNodes {
6737						// child removed, just resize parent rect
6738						node.branch[index].rect = d9nodeCover(node.branch[index].child)
6739					} else {
6740						// child removed, not enough entries in node, eliminate node
6741						d9reInsert(node.branch[index].child, listNode)
6742						d9disconnectBranch(node, index) // Must return after this call as count has changed
6743					}
6744					return false
6745				}
6746			}
6747		}
6748		return true
6749	} else { // A leaf node
6750		for index := 0; index < node.count; index++ {
6751			if node.branch[index].data == id {
6752				d9disconnectBranch(node, index) // Must return after this call as count has changed
6753				return false
6754			}
6755		}
6756		return true
6757	}
6758}
6759
6760// Decide whether two rectangles d9overlap.
6761func d9overlap(rectA, rectB d9rectT) bool {
6762	for index := 0; index < d9numDims; index++ {
6763		if rectA.min[index] > rectB.max[index] ||
6764			rectB.min[index] > rectA.max[index] {
6765			return false
6766		}
6767	}
6768	return true
6769}
6770
6771// Add a node to the reinsertion list.  All its branches will later
6772// be reinserted into the index structure.
6773func d9reInsert(node *d9nodeT, listNode **d9listNodeT) {
6774	newListNode := &d9listNodeT{}
6775	newListNode.node = node
6776	newListNode.next = *listNode
6777	*listNode = newListNode
6778}
6779
6780// d9search in an index tree or subtree for all data retangles that d9overlap the argument rectangle.
6781func d9search(node *d9nodeT, rect d9rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
6782	if node.isInternalNode() {
6783		// This is an internal node in the tree
6784		for index := 0; index < node.count; index++ {
6785			if d9overlap(rect, node.branch[index].rect) {
6786				var ok bool
6787				foundCount, ok = d9search(node.branch[index].child, rect, foundCount, resultCallback)
6788				if !ok {
6789					// The callback indicated to stop searching
6790					return foundCount, false
6791				}
6792			}
6793		}
6794	} else {
6795		// This is a leaf node
6796		for index := 0; index < node.count; index++ {
6797			if d9overlap(rect, node.branch[index].rect) {
6798				id := node.branch[index].data
6799				foundCount++
6800				if !resultCallback(id) {
6801					return foundCount, false // Don't continue searching
6802				}
6803
6804			}
6805		}
6806	}
6807	return foundCount, true // Continue searching
6808}
6809
6810func d10fmin(a, b float64) float64 {
6811	if a < b {
6812		return a
6813	}
6814	return b
6815}
6816func d10fmax(a, b float64) float64 {
6817	if a > b {
6818		return a
6819	}
6820	return b
6821}
6822
6823const (
6824	d10numDims            = 10
6825	d10maxNodes           = 8
6826	d10minNodes           = d10maxNodes / 2
6827	d10useSphericalVolume = true // Better split classification, may be slower on some systems
6828)
6829
6830var d10unitSphereVolume = []float64{
6831	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
6832	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
6833	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
6834	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
6835	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
6836	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
6837	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
6838}[d10numDims]
6839
6840type d10RTree struct {
6841	root *d10nodeT ///< Root of tree
6842}
6843
6844/// Minimal bounding rectangle (n-dimensional)
6845type d10rectT struct {
6846	min [d10numDims]float64 ///< Min dimensions of bounding box
6847	max [d10numDims]float64 ///< Max dimensions of bounding box
6848}
6849
6850/// May be data or may be another subtree
6851/// The parents level determines this.
6852/// If the parents level is 0, then this is data
6853type d10branchT struct {
6854	rect  d10rectT    ///< Bounds
6855	child *d10nodeT   ///< Child node
6856	data  interface{} ///< Data Id or Ptr
6857}
6858
6859/// d10nodeT for each branch level
6860type d10nodeT struct {
6861	count  int                     ///< Count
6862	level  int                     ///< Leaf is zero, others positive
6863	branch [d10maxNodes]d10branchT ///< Branch
6864}
6865
6866func (node *d10nodeT) isInternalNode() bool {
6867	return (node.level > 0) // Not a leaf, but a internal node
6868}
6869func (node *d10nodeT) isLeaf() bool {
6870	return (node.level == 0) // A leaf, contains data
6871}
6872
6873/// A link list of nodes for reinsertion after a delete operation
6874type d10listNodeT struct {
6875	next *d10listNodeT ///< Next in list
6876	node *d10nodeT     ///< Node
6877}
6878
6879const d10notTaken = -1 // indicates that position
6880
6881/// Variables for finding a split partition
6882type d10partitionVarsT struct {
6883	partition [d10maxNodes + 1]int
6884	total     int
6885	minFill   int
6886	count     [2]int
6887	cover     [2]d10rectT
6888	area      [2]float64
6889
6890	branchBuf      [d10maxNodes + 1]d10branchT
6891	branchCount    int
6892	coverSplit     d10rectT
6893	coverSplitArea float64
6894}
6895
6896func d10New() *d10RTree {
6897	// We only support machine word size simple data type eg. integer index or object pointer.
6898	// Since we are storing as union with non data branch
6899	return &d10RTree{
6900		root: &d10nodeT{},
6901	}
6902}
6903
6904/// Insert entry
6905/// \param a_min Min of bounding rect
6906/// \param a_max Max of bounding rect
6907/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
6908func (tr *d10RTree) Insert(min, max [d10numDims]float64, dataId interface{}) {
6909	var branch d10branchT
6910	branch.data = dataId
6911	for axis := 0; axis < d10numDims; axis++ {
6912		branch.rect.min[axis] = min[axis]
6913		branch.rect.max[axis] = max[axis]
6914	}
6915	d10insertRect(&branch, &tr.root, 0)
6916}
6917
6918/// Remove entry
6919/// \param a_min Min of bounding rect
6920/// \param a_max Max of bounding rect
6921/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
6922func (tr *d10RTree) Remove(min, max [d10numDims]float64, dataId interface{}) {
6923	var rect d10rectT
6924	for axis := 0; axis < d10numDims; axis++ {
6925		rect.min[axis] = min[axis]
6926		rect.max[axis] = max[axis]
6927	}
6928	d10removeRect(&rect, dataId, &tr.root)
6929}
6930
6931/// Find all within d10search rectangle
6932/// \param a_min Min of d10search bounding rect
6933/// \param a_max Max of d10search bounding rect
6934/// \param a_searchResult d10search result array.  Caller should set grow size. Function will reset, not append to array.
6935/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
6936/// \param a_context User context to pass as parameter to a_resultCallback
6937/// \return Returns the number of entries found
6938func (tr *d10RTree) Search(min, max [d10numDims]float64, resultCallback func(data interface{}) bool) int {
6939	var rect d10rectT
6940	for axis := 0; axis < d10numDims; axis++ {
6941		rect.min[axis] = min[axis]
6942		rect.max[axis] = max[axis]
6943	}
6944	foundCount, _ := d10search(tr.root, rect, 0, resultCallback)
6945	return foundCount
6946}
6947
6948/// Count the data elements in this container.  This is slow as no internal counter is maintained.
6949func (tr *d10RTree) Count() int {
6950	var count int
6951	d10countRec(tr.root, &count)
6952	return count
6953}
6954
6955/// Remove all entries from tree
6956func (tr *d10RTree) RemoveAll() {
6957	// Delete all existing nodes
6958	tr.root = &d10nodeT{}
6959}
6960
6961func d10countRec(node *d10nodeT, count *int) {
6962	if node.isInternalNode() { // not a leaf node
6963		for index := 0; index < node.count; index++ {
6964			d10countRec(node.branch[index].child, count)
6965		}
6966	} else { // A leaf node
6967		*count += node.count
6968	}
6969}
6970
6971// Inserts a new data rectangle into the index structure.
6972// Recursively descends tree, propagates splits back up.
6973// Returns 0 if node was not split.  Old node updated.
6974// If node was split, returns 1 and sets the pointer pointed to by
6975// new_node to point to the new node.  Old node updated to become one of two.
6976// The level argument specifies the number of steps up from the leaf
6977// level to insert; e.g. a data rectangle goes in at level = 0.
6978func d10insertRectRec(branch *d10branchT, node *d10nodeT, newNode **d10nodeT, level int) bool {
6979	// recurse until we reach the correct level for the new record. data records
6980	// will always be called with a_level == 0 (leaf)
6981	if node.level > level {
6982		// Still above level for insertion, go down tree recursively
6983		var otherNode *d10nodeT
6984		//var newBranch d10branchT
6985
6986		// find the optimal branch for this record
6987		index := d10pickBranch(&branch.rect, node)
6988
6989		// recursively insert this record into the picked branch
6990		childWasSplit := d10insertRectRec(branch, node.branch[index].child, &otherNode, level)
6991
6992		if !childWasSplit {
6993			// Child was not split. Merge the bounding box of the new record with the
6994			// existing bounding box
6995			node.branch[index].rect = d10combineRect(&branch.rect, &(node.branch[index].rect))
6996			return false
6997		} else {
6998			// Child was split. The old branches are now re-partitioned to two nodes
6999			// so we have to re-calculate the bounding boxes of each node
7000			node.branch[index].rect = d10nodeCover(node.branch[index].child)
7001			var newBranch d10branchT
7002			newBranch.child = otherNode
7003			newBranch.rect = d10nodeCover(otherNode)
7004
7005			// The old node is already a child of a_node. Now add the newly-created
7006			// node to a_node as well. a_node might be split because of that.
7007			return d10addBranch(&newBranch, node, newNode)
7008		}
7009	} else if node.level == level {
7010		// We have reached level for insertion. Add rect, split if necessary
7011		return d10addBranch(branch, node, newNode)
7012	} else {
7013		// Should never occur
7014		return false
7015	}
7016}
7017
7018// Insert a data rectangle into an index structure.
7019// d10insertRect provides for splitting the root;
7020// returns 1 if root was split, 0 if it was not.
7021// The level argument specifies the number of steps up from the leaf
7022// level to insert; e.g. a data rectangle goes in at level = 0.
7023// InsertRect2 does the recursion.
7024//
7025func d10insertRect(branch *d10branchT, root **d10nodeT, level int) bool {
7026	var newNode *d10nodeT
7027
7028	if d10insertRectRec(branch, *root, &newNode, level) { // Root split
7029
7030		// Grow tree taller and new root
7031		newRoot := &d10nodeT{}
7032		newRoot.level = (*root).level + 1
7033
7034		var newBranch d10branchT
7035
7036		// add old root node as a child of the new root
7037		newBranch.rect = d10nodeCover(*root)
7038		newBranch.child = *root
7039		d10addBranch(&newBranch, newRoot, nil)
7040
7041		// add the split node as a child of the new root
7042		newBranch.rect = d10nodeCover(newNode)
7043		newBranch.child = newNode
7044		d10addBranch(&newBranch, newRoot, nil)
7045
7046		// set the new root as the root node
7047		*root = newRoot
7048
7049		return true
7050	}
7051	return false
7052}
7053
7054// Find the smallest rectangle that includes all rectangles in branches of a node.
7055func d10nodeCover(node *d10nodeT) d10rectT {
7056	rect := node.branch[0].rect
7057	for index := 1; index < node.count; index++ {
7058		rect = d10combineRect(&rect, &(node.branch[index].rect))
7059	}
7060	return rect
7061}
7062
7063// Add a branch to a node.  Split the node if necessary.
7064// Returns 0 if node not split.  Old node updated.
7065// Returns 1 if node split, sets *new_node to address of new node.
7066// Old node updated, becomes one of two.
7067func d10addBranch(branch *d10branchT, node *d10nodeT, newNode **d10nodeT) bool {
7068	if node.count < d10maxNodes { // Split won't be necessary
7069		node.branch[node.count] = *branch
7070		node.count++
7071		return false
7072	} else {
7073		d10splitNode(node, branch, newNode)
7074		return true
7075	}
7076}
7077
7078// Disconnect a dependent node.
7079// Caller must return (or stop using iteration index) after this as count has changed
7080func d10disconnectBranch(node *d10nodeT, index int) {
7081	// Remove element by swapping with the last element to prevent gaps in array
7082	node.branch[index] = node.branch[node.count-1]
7083	node.branch[node.count-1].data = nil
7084	node.branch[node.count-1].child = nil
7085	node.count--
7086}
7087
7088// Pick a branch.  Pick the one that will need the smallest increase
7089// in area to accomodate the new rectangle.  This will result in the
7090// least total area for the covering rectangles in the current node.
7091// In case of a tie, pick the one which was smaller before, to get
7092// the best resolution when searching.
7093func d10pickBranch(rect *d10rectT, node *d10nodeT) int {
7094	var firstTime bool = true
7095	var increase float64
7096	var bestIncr float64 = -1
7097	var area float64
7098	var bestArea float64
7099	var best int
7100	var tempRect d10rectT
7101
7102	for index := 0; index < node.count; index++ {
7103		curRect := &node.branch[index].rect
7104		area = d10calcRectVolume(curRect)
7105		tempRect = d10combineRect(rect, curRect)
7106		increase = d10calcRectVolume(&tempRect) - area
7107		if (increase < bestIncr) || firstTime {
7108			best = index
7109			bestArea = area
7110			bestIncr = increase
7111			firstTime = false
7112		} else if (increase == bestIncr) && (area < bestArea) {
7113			best = index
7114			bestArea = area
7115			bestIncr = increase
7116		}
7117	}
7118	return best
7119}
7120
7121// Combine two rectangles into larger one containing both
7122func d10combineRect(rectA, rectB *d10rectT) d10rectT {
7123	var newRect d10rectT
7124
7125	for index := 0; index < d10numDims; index++ {
7126		newRect.min[index] = d10fmin(rectA.min[index], rectB.min[index])
7127		newRect.max[index] = d10fmax(rectA.max[index], rectB.max[index])
7128	}
7129
7130	return newRect
7131}
7132
7133// Split a node.
7134// Divides the nodes branches and the extra one between two nodes.
7135// Old node is one of the new ones, and one really new one is created.
7136// Tries more than one method for choosing a partition, uses best result.
7137func d10splitNode(node *d10nodeT, branch *d10branchT, newNode **d10nodeT) {
7138	// Could just use local here, but member or external is faster since it is reused
7139	var localVars d10partitionVarsT
7140	parVars := &localVars
7141
7142	// Load all the branches into a buffer, initialize old node
7143	d10getBranches(node, branch, parVars)
7144
7145	// Find partition
7146	d10choosePartition(parVars, d10minNodes)
7147
7148	// Create a new node to hold (about) half of the branches
7149	*newNode = &d10nodeT{}
7150	(*newNode).level = node.level
7151
7152	// Put branches from buffer into 2 nodes according to the chosen partition
7153	node.count = 0
7154	d10loadNodes(node, *newNode, parVars)
7155}
7156
7157// Calculate the n-dimensional volume of a rectangle
7158func d10rectVolume(rect *d10rectT) float64 {
7159	var volume float64 = 1
7160	for index := 0; index < d10numDims; index++ {
7161		volume *= rect.max[index] - rect.min[index]
7162	}
7163	return volume
7164}
7165
7166// The exact volume of the bounding sphere for the given d10rectT
7167func d10rectSphericalVolume(rect *d10rectT) float64 {
7168	var sumOfSquares float64 = 0
7169	var radius float64
7170
7171	for index := 0; index < d10numDims; index++ {
7172		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
7173		sumOfSquares += halfExtent * halfExtent
7174	}
7175
7176	radius = math.Sqrt(sumOfSquares)
7177
7178	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
7179	if d10numDims == 5 {
7180		return (radius * radius * radius * radius * radius * d10unitSphereVolume)
7181	} else if d10numDims == 4 {
7182		return (radius * radius * radius * radius * d10unitSphereVolume)
7183	} else if d10numDims == 3 {
7184		return (radius * radius * radius * d10unitSphereVolume)
7185	} else if d10numDims == 2 {
7186		return (radius * radius * d10unitSphereVolume)
7187	} else {
7188		return (math.Pow(radius, d10numDims) * d10unitSphereVolume)
7189	}
7190}
7191
7192// Use one of the methods to calculate retangle volume
7193func d10calcRectVolume(rect *d10rectT) float64 {
7194	if d10useSphericalVolume {
7195		return d10rectSphericalVolume(rect) // Slower but helps certain merge cases
7196	} else { // RTREE_USE_SPHERICAL_VOLUME
7197		return d10rectVolume(rect) // Faster but can cause poor merges
7198	} // RTREE_USE_SPHERICAL_VOLUME
7199}
7200
7201// Load branch buffer with branches from full node plus the extra branch.
7202func d10getBranches(node *d10nodeT, branch *d10branchT, parVars *d10partitionVarsT) {
7203	// Load the branch buffer
7204	for index := 0; index < d10maxNodes; index++ {
7205		parVars.branchBuf[index] = node.branch[index]
7206	}
7207	parVars.branchBuf[d10maxNodes] = *branch
7208	parVars.branchCount = d10maxNodes + 1
7209
7210	// Calculate rect containing all in the set
7211	parVars.coverSplit = parVars.branchBuf[0].rect
7212	for index := 1; index < d10maxNodes+1; index++ {
7213		parVars.coverSplit = d10combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
7214	}
7215	parVars.coverSplitArea = d10calcRectVolume(&parVars.coverSplit)
7216}
7217
7218// Method #0 for choosing a partition:
7219// As the seeds for the two groups, pick the two rects that would waste the
7220// most area if covered by a single rectangle, i.e. evidently the worst pair
7221// to have in the same group.
7222// Of the remaining, one at a time is chosen to be put in one of the two groups.
7223// The one chosen is the one with the greatest difference in area expansion
7224// depending on which group - the rect most strongly attracted to one group
7225// and repelled from the other.
7226// If one group gets too full (more would force other group to violate min
7227// fill requirement) then other group gets the rest.
7228// These last are the ones that can go in either group most easily.
7229func d10choosePartition(parVars *d10partitionVarsT, minFill int) {
7230	var biggestDiff float64
7231	var group, chosen, betterGroup int
7232
7233	d10initParVars(parVars, parVars.branchCount, minFill)
7234	d10pickSeeds(parVars)
7235
7236	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
7237		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
7238		(parVars.count[1] < (parVars.total - parVars.minFill)) {
7239		biggestDiff = -1
7240		for index := 0; index < parVars.total; index++ {
7241			if d10notTaken == parVars.partition[index] {
7242				curRect := &parVars.branchBuf[index].rect
7243				rect0 := d10combineRect(curRect, &parVars.cover[0])
7244				rect1 := d10combineRect(curRect, &parVars.cover[1])
7245				growth0 := d10calcRectVolume(&rect0) - parVars.area[0]
7246				growth1 := d10calcRectVolume(&rect1) - parVars.area[1]
7247				diff := growth1 - growth0
7248				if diff >= 0 {
7249					group = 0
7250				} else {
7251					group = 1
7252					diff = -diff
7253				}
7254
7255				if diff > biggestDiff {
7256					biggestDiff = diff
7257					chosen = index
7258					betterGroup = group
7259				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
7260					chosen = index
7261					betterGroup = group
7262				}
7263			}
7264		}
7265		d10classify(chosen, betterGroup, parVars)
7266	}
7267
7268	// If one group too full, put remaining rects in the other
7269	if (parVars.count[0] + parVars.count[1]) < parVars.total {
7270		if parVars.count[0] >= parVars.total-parVars.minFill {
7271			group = 1
7272		} else {
7273			group = 0
7274		}
7275		for index := 0; index < parVars.total; index++ {
7276			if d10notTaken == parVars.partition[index] {
7277				d10classify(index, group, parVars)
7278			}
7279		}
7280	}
7281}
7282
7283// Copy branches from the buffer into two nodes according to the partition.
7284func d10loadNodes(nodeA, nodeB *d10nodeT, parVars *d10partitionVarsT) {
7285	for index := 0; index < parVars.total; index++ {
7286		targetNodeIndex := parVars.partition[index]
7287		targetNodes := []*d10nodeT{nodeA, nodeB}
7288
7289		// It is assured that d10addBranch here will not cause a node split.
7290		d10addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
7291	}
7292}
7293
7294// Initialize a d10partitionVarsT structure.
7295func d10initParVars(parVars *d10partitionVarsT, maxRects, minFill int) {
7296	parVars.count[0] = 0
7297	parVars.count[1] = 0
7298	parVars.area[0] = 0
7299	parVars.area[1] = 0
7300	parVars.total = maxRects
7301	parVars.minFill = minFill
7302	for index := 0; index < maxRects; index++ {
7303		parVars.partition[index] = d10notTaken
7304	}
7305}
7306
7307func d10pickSeeds(parVars *d10partitionVarsT) {
7308	var seed0, seed1 int
7309	var worst, waste float64
7310	var area [d10maxNodes + 1]float64
7311
7312	for index := 0; index < parVars.total; index++ {
7313		area[index] = d10calcRectVolume(&parVars.branchBuf[index].rect)
7314	}
7315
7316	worst = -parVars.coverSplitArea - 1
7317	for indexA := 0; indexA < parVars.total-1; indexA++ {
7318		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
7319			oneRect := d10combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
7320			waste = d10calcRectVolume(&oneRect) - area[indexA] - area[indexB]
7321			if waste > worst {
7322				worst = waste
7323				seed0 = indexA
7324				seed1 = indexB
7325			}
7326		}
7327	}
7328
7329	d10classify(seed0, 0, parVars)
7330	d10classify(seed1, 1, parVars)
7331}
7332
7333// Put a branch in one of the groups.
7334func d10classify(index, group int, parVars *d10partitionVarsT) {
7335	parVars.partition[index] = group
7336
7337	// Calculate combined rect
7338	if parVars.count[group] == 0 {
7339		parVars.cover[group] = parVars.branchBuf[index].rect
7340	} else {
7341		parVars.cover[group] = d10combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
7342	}
7343
7344	// Calculate volume of combined rect
7345	parVars.area[group] = d10calcRectVolume(&parVars.cover[group])
7346
7347	parVars.count[group]++
7348}
7349
7350// Delete a data rectangle from an index structure.
7351// Pass in a pointer to a d10rectT, the tid of the record, ptr to ptr to root node.
7352// Returns 1 if record not found, 0 if success.
7353// d10removeRect provides for eliminating the root.
7354func d10removeRect(rect *d10rectT, id interface{}, root **d10nodeT) bool {
7355	var reInsertList *d10listNodeT
7356
7357	if !d10removeRectRec(rect, id, *root, &reInsertList) {
7358		// Found and deleted a data item
7359		// Reinsert any branches from eliminated nodes
7360		for reInsertList != nil {
7361			tempNode := reInsertList.node
7362
7363			for index := 0; index < tempNode.count; index++ {
7364				// TODO go over this code. should I use (tempNode->m_level - 1)?
7365				d10insertRect(&tempNode.branch[index], root, tempNode.level)
7366			}
7367			reInsertList = reInsertList.next
7368		}
7369
7370		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
7371		// if with while? In case there is a whole branch of redundant roots...
7372		if (*root).count == 1 && (*root).isInternalNode() {
7373			tempNode := (*root).branch[0].child
7374			*root = tempNode
7375		}
7376		return false
7377	} else {
7378		return true
7379	}
7380}
7381
7382// Delete a rectangle from non-root part of an index structure.
7383// Called by d10removeRect.  Descends tree recursively,
7384// merges branches on the way back up.
7385// Returns 1 if record not found, 0 if success.
7386func d10removeRectRec(rect *d10rectT, id interface{}, node *d10nodeT, listNode **d10listNodeT) bool {
7387	if node.isInternalNode() { // not a leaf node
7388		for index := 0; index < node.count; index++ {
7389			if d10overlap(*rect, node.branch[index].rect) {
7390				if !d10removeRectRec(rect, id, node.branch[index].child, listNode) {
7391					if node.branch[index].child.count >= d10minNodes {
7392						// child removed, just resize parent rect
7393						node.branch[index].rect = d10nodeCover(node.branch[index].child)
7394					} else {
7395						// child removed, not enough entries in node, eliminate node
7396						d10reInsert(node.branch[index].child, listNode)
7397						d10disconnectBranch(node, index) // Must return after this call as count has changed
7398					}
7399					return false
7400				}
7401			}
7402		}
7403		return true
7404	} else { // A leaf node
7405		for index := 0; index < node.count; index++ {
7406			if node.branch[index].data == id {
7407				d10disconnectBranch(node, index) // Must return after this call as count has changed
7408				return false
7409			}
7410		}
7411		return true
7412	}
7413}
7414
7415// Decide whether two rectangles d10overlap.
7416func d10overlap(rectA, rectB d10rectT) bool {
7417	for index := 0; index < d10numDims; index++ {
7418		if rectA.min[index] > rectB.max[index] ||
7419			rectB.min[index] > rectA.max[index] {
7420			return false
7421		}
7422	}
7423	return true
7424}
7425
7426// Add a node to the reinsertion list.  All its branches will later
7427// be reinserted into the index structure.
7428func d10reInsert(node *d10nodeT, listNode **d10listNodeT) {
7429	newListNode := &d10listNodeT{}
7430	newListNode.node = node
7431	newListNode.next = *listNode
7432	*listNode = newListNode
7433}
7434
7435// d10search in an index tree or subtree for all data retangles that d10overlap the argument rectangle.
7436func d10search(node *d10nodeT, rect d10rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
7437	if node.isInternalNode() {
7438		// This is an internal node in the tree
7439		for index := 0; index < node.count; index++ {
7440			if d10overlap(rect, node.branch[index].rect) {
7441				var ok bool
7442				foundCount, ok = d10search(node.branch[index].child, rect, foundCount, resultCallback)
7443				if !ok {
7444					// The callback indicated to stop searching
7445					return foundCount, false
7446				}
7447			}
7448		}
7449	} else {
7450		// This is a leaf node
7451		for index := 0; index < node.count; index++ {
7452			if d10overlap(rect, node.branch[index].rect) {
7453				id := node.branch[index].data
7454				foundCount++
7455				if !resultCallback(id) {
7456					return foundCount, false // Don't continue searching
7457				}
7458
7459			}
7460		}
7461	}
7462	return foundCount, true // Continue searching
7463}
7464
7465func d11fmin(a, b float64) float64 {
7466	if a < b {
7467		return a
7468	}
7469	return b
7470}
7471func d11fmax(a, b float64) float64 {
7472	if a > b {
7473		return a
7474	}
7475	return b
7476}
7477
7478const (
7479	d11numDims            = 11
7480	d11maxNodes           = 8
7481	d11minNodes           = d11maxNodes / 2
7482	d11useSphericalVolume = true // Better split classification, may be slower on some systems
7483)
7484
7485var d11unitSphereVolume = []float64{
7486	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
7487	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
7488	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
7489	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
7490	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
7491	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
7492	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
7493}[d11numDims]
7494
7495type d11RTree struct {
7496	root *d11nodeT ///< Root of tree
7497}
7498
7499/// Minimal bounding rectangle (n-dimensional)
7500type d11rectT struct {
7501	min [d11numDims]float64 ///< Min dimensions of bounding box
7502	max [d11numDims]float64 ///< Max dimensions of bounding box
7503}
7504
7505/// May be data or may be another subtree
7506/// The parents level determines this.
7507/// If the parents level is 0, then this is data
7508type d11branchT struct {
7509	rect  d11rectT    ///< Bounds
7510	child *d11nodeT   ///< Child node
7511	data  interface{} ///< Data Id or Ptr
7512}
7513
7514/// d11nodeT for each branch level
7515type d11nodeT struct {
7516	count  int                     ///< Count
7517	level  int                     ///< Leaf is zero, others positive
7518	branch [d11maxNodes]d11branchT ///< Branch
7519}
7520
7521func (node *d11nodeT) isInternalNode() bool {
7522	return (node.level > 0) // Not a leaf, but a internal node
7523}
7524func (node *d11nodeT) isLeaf() bool {
7525	return (node.level == 0) // A leaf, contains data
7526}
7527
7528/// A link list of nodes for reinsertion after a delete operation
7529type d11listNodeT struct {
7530	next *d11listNodeT ///< Next in list
7531	node *d11nodeT     ///< Node
7532}
7533
7534const d11notTaken = -1 // indicates that position
7535
7536/// Variables for finding a split partition
7537type d11partitionVarsT struct {
7538	partition [d11maxNodes + 1]int
7539	total     int
7540	minFill   int
7541	count     [2]int
7542	cover     [2]d11rectT
7543	area      [2]float64
7544
7545	branchBuf      [d11maxNodes + 1]d11branchT
7546	branchCount    int
7547	coverSplit     d11rectT
7548	coverSplitArea float64
7549}
7550
7551func d11New() *d11RTree {
7552	// We only support machine word size simple data type eg. integer index or object pointer.
7553	// Since we are storing as union with non data branch
7554	return &d11RTree{
7555		root: &d11nodeT{},
7556	}
7557}
7558
7559/// Insert entry
7560/// \param a_min Min of bounding rect
7561/// \param a_max Max of bounding rect
7562/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
7563func (tr *d11RTree) Insert(min, max [d11numDims]float64, dataId interface{}) {
7564	var branch d11branchT
7565	branch.data = dataId
7566	for axis := 0; axis < d11numDims; axis++ {
7567		branch.rect.min[axis] = min[axis]
7568		branch.rect.max[axis] = max[axis]
7569	}
7570	d11insertRect(&branch, &tr.root, 0)
7571}
7572
7573/// Remove entry
7574/// \param a_min Min of bounding rect
7575/// \param a_max Max of bounding rect
7576/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
7577func (tr *d11RTree) Remove(min, max [d11numDims]float64, dataId interface{}) {
7578	var rect d11rectT
7579	for axis := 0; axis < d11numDims; axis++ {
7580		rect.min[axis] = min[axis]
7581		rect.max[axis] = max[axis]
7582	}
7583	d11removeRect(&rect, dataId, &tr.root)
7584}
7585
7586/// Find all within d11search rectangle
7587/// \param a_min Min of d11search bounding rect
7588/// \param a_max Max of d11search bounding rect
7589/// \param a_searchResult d11search result array.  Caller should set grow size. Function will reset, not append to array.
7590/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
7591/// \param a_context User context to pass as parameter to a_resultCallback
7592/// \return Returns the number of entries found
7593func (tr *d11RTree) Search(min, max [d11numDims]float64, resultCallback func(data interface{}) bool) int {
7594	var rect d11rectT
7595	for axis := 0; axis < d11numDims; axis++ {
7596		rect.min[axis] = min[axis]
7597		rect.max[axis] = max[axis]
7598	}
7599	foundCount, _ := d11search(tr.root, rect, 0, resultCallback)
7600	return foundCount
7601}
7602
7603/// Count the data elements in this container.  This is slow as no internal counter is maintained.
7604func (tr *d11RTree) Count() int {
7605	var count int
7606	d11countRec(tr.root, &count)
7607	return count
7608}
7609
7610/// Remove all entries from tree
7611func (tr *d11RTree) RemoveAll() {
7612	// Delete all existing nodes
7613	tr.root = &d11nodeT{}
7614}
7615
7616func d11countRec(node *d11nodeT, count *int) {
7617	if node.isInternalNode() { // not a leaf node
7618		for index := 0; index < node.count; index++ {
7619			d11countRec(node.branch[index].child, count)
7620		}
7621	} else { // A leaf node
7622		*count += node.count
7623	}
7624}
7625
7626// Inserts a new data rectangle into the index structure.
7627// Recursively descends tree, propagates splits back up.
7628// Returns 0 if node was not split.  Old node updated.
7629// If node was split, returns 1 and sets the pointer pointed to by
7630// new_node to point to the new node.  Old node updated to become one of two.
7631// The level argument specifies the number of steps up from the leaf
7632// level to insert; e.g. a data rectangle goes in at level = 0.
7633func d11insertRectRec(branch *d11branchT, node *d11nodeT, newNode **d11nodeT, level int) bool {
7634	// recurse until we reach the correct level for the new record. data records
7635	// will always be called with a_level == 0 (leaf)
7636	if node.level > level {
7637		// Still above level for insertion, go down tree recursively
7638		var otherNode *d11nodeT
7639		//var newBranch d11branchT
7640
7641		// find the optimal branch for this record
7642		index := d11pickBranch(&branch.rect, node)
7643
7644		// recursively insert this record into the picked branch
7645		childWasSplit := d11insertRectRec(branch, node.branch[index].child, &otherNode, level)
7646
7647		if !childWasSplit {
7648			// Child was not split. Merge the bounding box of the new record with the
7649			// existing bounding box
7650			node.branch[index].rect = d11combineRect(&branch.rect, &(node.branch[index].rect))
7651			return false
7652		} else {
7653			// Child was split. The old branches are now re-partitioned to two nodes
7654			// so we have to re-calculate the bounding boxes of each node
7655			node.branch[index].rect = d11nodeCover(node.branch[index].child)
7656			var newBranch d11branchT
7657			newBranch.child = otherNode
7658			newBranch.rect = d11nodeCover(otherNode)
7659
7660			// The old node is already a child of a_node. Now add the newly-created
7661			// node to a_node as well. a_node might be split because of that.
7662			return d11addBranch(&newBranch, node, newNode)
7663		}
7664	} else if node.level == level {
7665		// We have reached level for insertion. Add rect, split if necessary
7666		return d11addBranch(branch, node, newNode)
7667	} else {
7668		// Should never occur
7669		return false
7670	}
7671}
7672
7673// Insert a data rectangle into an index structure.
7674// d11insertRect provides for splitting the root;
7675// returns 1 if root was split, 0 if it was not.
7676// The level argument specifies the number of steps up from the leaf
7677// level to insert; e.g. a data rectangle goes in at level = 0.
7678// InsertRect2 does the recursion.
7679//
7680func d11insertRect(branch *d11branchT, root **d11nodeT, level int) bool {
7681	var newNode *d11nodeT
7682
7683	if d11insertRectRec(branch, *root, &newNode, level) { // Root split
7684
7685		// Grow tree taller and new root
7686		newRoot := &d11nodeT{}
7687		newRoot.level = (*root).level + 1
7688
7689		var newBranch d11branchT
7690
7691		// add old root node as a child of the new root
7692		newBranch.rect = d11nodeCover(*root)
7693		newBranch.child = *root
7694		d11addBranch(&newBranch, newRoot, nil)
7695
7696		// add the split node as a child of the new root
7697		newBranch.rect = d11nodeCover(newNode)
7698		newBranch.child = newNode
7699		d11addBranch(&newBranch, newRoot, nil)
7700
7701		// set the new root as the root node
7702		*root = newRoot
7703
7704		return true
7705	}
7706	return false
7707}
7708
7709// Find the smallest rectangle that includes all rectangles in branches of a node.
7710func d11nodeCover(node *d11nodeT) d11rectT {
7711	rect := node.branch[0].rect
7712	for index := 1; index < node.count; index++ {
7713		rect = d11combineRect(&rect, &(node.branch[index].rect))
7714	}
7715	return rect
7716}
7717
7718// Add a branch to a node.  Split the node if necessary.
7719// Returns 0 if node not split.  Old node updated.
7720// Returns 1 if node split, sets *new_node to address of new node.
7721// Old node updated, becomes one of two.
7722func d11addBranch(branch *d11branchT, node *d11nodeT, newNode **d11nodeT) bool {
7723	if node.count < d11maxNodes { // Split won't be necessary
7724		node.branch[node.count] = *branch
7725		node.count++
7726		return false
7727	} else {
7728		d11splitNode(node, branch, newNode)
7729		return true
7730	}
7731}
7732
7733// Disconnect a dependent node.
7734// Caller must return (or stop using iteration index) after this as count has changed
7735func d11disconnectBranch(node *d11nodeT, index int) {
7736	// Remove element by swapping with the last element to prevent gaps in array
7737	node.branch[index] = node.branch[node.count-1]
7738	node.branch[node.count-1].data = nil
7739	node.branch[node.count-1].child = nil
7740	node.count--
7741}
7742
7743// Pick a branch.  Pick the one that will need the smallest increase
7744// in area to accomodate the new rectangle.  This will result in the
7745// least total area for the covering rectangles in the current node.
7746// In case of a tie, pick the one which was smaller before, to get
7747// the best resolution when searching.
7748func d11pickBranch(rect *d11rectT, node *d11nodeT) int {
7749	var firstTime bool = true
7750	var increase float64
7751	var bestIncr float64 = -1
7752	var area float64
7753	var bestArea float64
7754	var best int
7755	var tempRect d11rectT
7756
7757	for index := 0; index < node.count; index++ {
7758		curRect := &node.branch[index].rect
7759		area = d11calcRectVolume(curRect)
7760		tempRect = d11combineRect(rect, curRect)
7761		increase = d11calcRectVolume(&tempRect) - area
7762		if (increase < bestIncr) || firstTime {
7763			best = index
7764			bestArea = area
7765			bestIncr = increase
7766			firstTime = false
7767		} else if (increase == bestIncr) && (area < bestArea) {
7768			best = index
7769			bestArea = area
7770			bestIncr = increase
7771		}
7772	}
7773	return best
7774}
7775
7776// Combine two rectangles into larger one containing both
7777func d11combineRect(rectA, rectB *d11rectT) d11rectT {
7778	var newRect d11rectT
7779
7780	for index := 0; index < d11numDims; index++ {
7781		newRect.min[index] = d11fmin(rectA.min[index], rectB.min[index])
7782		newRect.max[index] = d11fmax(rectA.max[index], rectB.max[index])
7783	}
7784
7785	return newRect
7786}
7787
7788// Split a node.
7789// Divides the nodes branches and the extra one between two nodes.
7790// Old node is one of the new ones, and one really new one is created.
7791// Tries more than one method for choosing a partition, uses best result.
7792func d11splitNode(node *d11nodeT, branch *d11branchT, newNode **d11nodeT) {
7793	// Could just use local here, but member or external is faster since it is reused
7794	var localVars d11partitionVarsT
7795	parVars := &localVars
7796
7797	// Load all the branches into a buffer, initialize old node
7798	d11getBranches(node, branch, parVars)
7799
7800	// Find partition
7801	d11choosePartition(parVars, d11minNodes)
7802
7803	// Create a new node to hold (about) half of the branches
7804	*newNode = &d11nodeT{}
7805	(*newNode).level = node.level
7806
7807	// Put branches from buffer into 2 nodes according to the chosen partition
7808	node.count = 0
7809	d11loadNodes(node, *newNode, parVars)
7810}
7811
7812// Calculate the n-dimensional volume of a rectangle
7813func d11rectVolume(rect *d11rectT) float64 {
7814	var volume float64 = 1
7815	for index := 0; index < d11numDims; index++ {
7816		volume *= rect.max[index] - rect.min[index]
7817	}
7818	return volume
7819}
7820
7821// The exact volume of the bounding sphere for the given d11rectT
7822func d11rectSphericalVolume(rect *d11rectT) float64 {
7823	var sumOfSquares float64 = 0
7824	var radius float64
7825
7826	for index := 0; index < d11numDims; index++ {
7827		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
7828		sumOfSquares += halfExtent * halfExtent
7829	}
7830
7831	radius = math.Sqrt(sumOfSquares)
7832
7833	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
7834	if d11numDims == 5 {
7835		return (radius * radius * radius * radius * radius * d11unitSphereVolume)
7836	} else if d11numDims == 4 {
7837		return (radius * radius * radius * radius * d11unitSphereVolume)
7838	} else if d11numDims == 3 {
7839		return (radius * radius * radius * d11unitSphereVolume)
7840	} else if d11numDims == 2 {
7841		return (radius * radius * d11unitSphereVolume)
7842	} else {
7843		return (math.Pow(radius, d11numDims) * d11unitSphereVolume)
7844	}
7845}
7846
7847// Use one of the methods to calculate retangle volume
7848func d11calcRectVolume(rect *d11rectT) float64 {
7849	if d11useSphericalVolume {
7850		return d11rectSphericalVolume(rect) // Slower but helps certain merge cases
7851	} else { // RTREE_USE_SPHERICAL_VOLUME
7852		return d11rectVolume(rect) // Faster but can cause poor merges
7853	} // RTREE_USE_SPHERICAL_VOLUME
7854}
7855
7856// Load branch buffer with branches from full node plus the extra branch.
7857func d11getBranches(node *d11nodeT, branch *d11branchT, parVars *d11partitionVarsT) {
7858	// Load the branch buffer
7859	for index := 0; index < d11maxNodes; index++ {
7860		parVars.branchBuf[index] = node.branch[index]
7861	}
7862	parVars.branchBuf[d11maxNodes] = *branch
7863	parVars.branchCount = d11maxNodes + 1
7864
7865	// Calculate rect containing all in the set
7866	parVars.coverSplit = parVars.branchBuf[0].rect
7867	for index := 1; index < d11maxNodes+1; index++ {
7868		parVars.coverSplit = d11combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
7869	}
7870	parVars.coverSplitArea = d11calcRectVolume(&parVars.coverSplit)
7871}
7872
7873// Method #0 for choosing a partition:
7874// As the seeds for the two groups, pick the two rects that would waste the
7875// most area if covered by a single rectangle, i.e. evidently the worst pair
7876// to have in the same group.
7877// Of the remaining, one at a time is chosen to be put in one of the two groups.
7878// The one chosen is the one with the greatest difference in area expansion
7879// depending on which group - the rect most strongly attracted to one group
7880// and repelled from the other.
7881// If one group gets too full (more would force other group to violate min
7882// fill requirement) then other group gets the rest.
7883// These last are the ones that can go in either group most easily.
7884func d11choosePartition(parVars *d11partitionVarsT, minFill int) {
7885	var biggestDiff float64
7886	var group, chosen, betterGroup int
7887
7888	d11initParVars(parVars, parVars.branchCount, minFill)
7889	d11pickSeeds(parVars)
7890
7891	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
7892		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
7893		(parVars.count[1] < (parVars.total - parVars.minFill)) {
7894		biggestDiff = -1
7895		for index := 0; index < parVars.total; index++ {
7896			if d11notTaken == parVars.partition[index] {
7897				curRect := &parVars.branchBuf[index].rect
7898				rect0 := d11combineRect(curRect, &parVars.cover[0])
7899				rect1 := d11combineRect(curRect, &parVars.cover[1])
7900				growth0 := d11calcRectVolume(&rect0) - parVars.area[0]
7901				growth1 := d11calcRectVolume(&rect1) - parVars.area[1]
7902				diff := growth1 - growth0
7903				if diff >= 0 {
7904					group = 0
7905				} else {
7906					group = 1
7907					diff = -diff
7908				}
7909
7910				if diff > biggestDiff {
7911					biggestDiff = diff
7912					chosen = index
7913					betterGroup = group
7914				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
7915					chosen = index
7916					betterGroup = group
7917				}
7918			}
7919		}
7920		d11classify(chosen, betterGroup, parVars)
7921	}
7922
7923	// If one group too full, put remaining rects in the other
7924	if (parVars.count[0] + parVars.count[1]) < parVars.total {
7925		if parVars.count[0] >= parVars.total-parVars.minFill {
7926			group = 1
7927		} else {
7928			group = 0
7929		}
7930		for index := 0; index < parVars.total; index++ {
7931			if d11notTaken == parVars.partition[index] {
7932				d11classify(index, group, parVars)
7933			}
7934		}
7935	}
7936}
7937
7938// Copy branches from the buffer into two nodes according to the partition.
7939func d11loadNodes(nodeA, nodeB *d11nodeT, parVars *d11partitionVarsT) {
7940	for index := 0; index < parVars.total; index++ {
7941		targetNodeIndex := parVars.partition[index]
7942		targetNodes := []*d11nodeT{nodeA, nodeB}
7943
7944		// It is assured that d11addBranch here will not cause a node split.
7945		d11addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
7946	}
7947}
7948
7949// Initialize a d11partitionVarsT structure.
7950func d11initParVars(parVars *d11partitionVarsT, maxRects, minFill int) {
7951	parVars.count[0] = 0
7952	parVars.count[1] = 0
7953	parVars.area[0] = 0
7954	parVars.area[1] = 0
7955	parVars.total = maxRects
7956	parVars.minFill = minFill
7957	for index := 0; index < maxRects; index++ {
7958		parVars.partition[index] = d11notTaken
7959	}
7960}
7961
7962func d11pickSeeds(parVars *d11partitionVarsT) {
7963	var seed0, seed1 int
7964	var worst, waste float64
7965	var area [d11maxNodes + 1]float64
7966
7967	for index := 0; index < parVars.total; index++ {
7968		area[index] = d11calcRectVolume(&parVars.branchBuf[index].rect)
7969	}
7970
7971	worst = -parVars.coverSplitArea - 1
7972	for indexA := 0; indexA < parVars.total-1; indexA++ {
7973		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
7974			oneRect := d11combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
7975			waste = d11calcRectVolume(&oneRect) - area[indexA] - area[indexB]
7976			if waste > worst {
7977				worst = waste
7978				seed0 = indexA
7979				seed1 = indexB
7980			}
7981		}
7982	}
7983
7984	d11classify(seed0, 0, parVars)
7985	d11classify(seed1, 1, parVars)
7986}
7987
7988// Put a branch in one of the groups.
7989func d11classify(index, group int, parVars *d11partitionVarsT) {
7990	parVars.partition[index] = group
7991
7992	// Calculate combined rect
7993	if parVars.count[group] == 0 {
7994		parVars.cover[group] = parVars.branchBuf[index].rect
7995	} else {
7996		parVars.cover[group] = d11combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
7997	}
7998
7999	// Calculate volume of combined rect
8000	parVars.area[group] = d11calcRectVolume(&parVars.cover[group])
8001
8002	parVars.count[group]++
8003}
8004
8005// Delete a data rectangle from an index structure.
8006// Pass in a pointer to a d11rectT, the tid of the record, ptr to ptr to root node.
8007// Returns 1 if record not found, 0 if success.
8008// d11removeRect provides for eliminating the root.
8009func d11removeRect(rect *d11rectT, id interface{}, root **d11nodeT) bool {
8010	var reInsertList *d11listNodeT
8011
8012	if !d11removeRectRec(rect, id, *root, &reInsertList) {
8013		// Found and deleted a data item
8014		// Reinsert any branches from eliminated nodes
8015		for reInsertList != nil {
8016			tempNode := reInsertList.node
8017
8018			for index := 0; index < tempNode.count; index++ {
8019				// TODO go over this code. should I use (tempNode->m_level - 1)?
8020				d11insertRect(&tempNode.branch[index], root, tempNode.level)
8021			}
8022			reInsertList = reInsertList.next
8023		}
8024
8025		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
8026		// if with while? In case there is a whole branch of redundant roots...
8027		if (*root).count == 1 && (*root).isInternalNode() {
8028			tempNode := (*root).branch[0].child
8029			*root = tempNode
8030		}
8031		return false
8032	} else {
8033		return true
8034	}
8035}
8036
8037// Delete a rectangle from non-root part of an index structure.
8038// Called by d11removeRect.  Descends tree recursively,
8039// merges branches on the way back up.
8040// Returns 1 if record not found, 0 if success.
8041func d11removeRectRec(rect *d11rectT, id interface{}, node *d11nodeT, listNode **d11listNodeT) bool {
8042	if node.isInternalNode() { // not a leaf node
8043		for index := 0; index < node.count; index++ {
8044			if d11overlap(*rect, node.branch[index].rect) {
8045				if !d11removeRectRec(rect, id, node.branch[index].child, listNode) {
8046					if node.branch[index].child.count >= d11minNodes {
8047						// child removed, just resize parent rect
8048						node.branch[index].rect = d11nodeCover(node.branch[index].child)
8049					} else {
8050						// child removed, not enough entries in node, eliminate node
8051						d11reInsert(node.branch[index].child, listNode)
8052						d11disconnectBranch(node, index) // Must return after this call as count has changed
8053					}
8054					return false
8055				}
8056			}
8057		}
8058		return true
8059	} else { // A leaf node
8060		for index := 0; index < node.count; index++ {
8061			if node.branch[index].data == id {
8062				d11disconnectBranch(node, index) // Must return after this call as count has changed
8063				return false
8064			}
8065		}
8066		return true
8067	}
8068}
8069
8070// Decide whether two rectangles d11overlap.
8071func d11overlap(rectA, rectB d11rectT) bool {
8072	for index := 0; index < d11numDims; index++ {
8073		if rectA.min[index] > rectB.max[index] ||
8074			rectB.min[index] > rectA.max[index] {
8075			return false
8076		}
8077	}
8078	return true
8079}
8080
8081// Add a node to the reinsertion list.  All its branches will later
8082// be reinserted into the index structure.
8083func d11reInsert(node *d11nodeT, listNode **d11listNodeT) {
8084	newListNode := &d11listNodeT{}
8085	newListNode.node = node
8086	newListNode.next = *listNode
8087	*listNode = newListNode
8088}
8089
8090// d11search in an index tree or subtree for all data retangles that d11overlap the argument rectangle.
8091func d11search(node *d11nodeT, rect d11rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
8092	if node.isInternalNode() {
8093		// This is an internal node in the tree
8094		for index := 0; index < node.count; index++ {
8095			if d11overlap(rect, node.branch[index].rect) {
8096				var ok bool
8097				foundCount, ok = d11search(node.branch[index].child, rect, foundCount, resultCallback)
8098				if !ok {
8099					// The callback indicated to stop searching
8100					return foundCount, false
8101				}
8102			}
8103		}
8104	} else {
8105		// This is a leaf node
8106		for index := 0; index < node.count; index++ {
8107			if d11overlap(rect, node.branch[index].rect) {
8108				id := node.branch[index].data
8109				foundCount++
8110				if !resultCallback(id) {
8111					return foundCount, false // Don't continue searching
8112				}
8113
8114			}
8115		}
8116	}
8117	return foundCount, true // Continue searching
8118}
8119
8120func d12fmin(a, b float64) float64 {
8121	if a < b {
8122		return a
8123	}
8124	return b
8125}
8126func d12fmax(a, b float64) float64 {
8127	if a > b {
8128		return a
8129	}
8130	return b
8131}
8132
8133const (
8134	d12numDims            = 12
8135	d12maxNodes           = 8
8136	d12minNodes           = d12maxNodes / 2
8137	d12useSphericalVolume = true // Better split classification, may be slower on some systems
8138)
8139
8140var d12unitSphereVolume = []float64{
8141	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
8142	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
8143	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
8144	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
8145	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
8146	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
8147	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
8148}[d12numDims]
8149
8150type d12RTree struct {
8151	root *d12nodeT ///< Root of tree
8152}
8153
8154/// Minimal bounding rectangle (n-dimensional)
8155type d12rectT struct {
8156	min [d12numDims]float64 ///< Min dimensions of bounding box
8157	max [d12numDims]float64 ///< Max dimensions of bounding box
8158}
8159
8160/// May be data or may be another subtree
8161/// The parents level determines this.
8162/// If the parents level is 0, then this is data
8163type d12branchT struct {
8164	rect  d12rectT    ///< Bounds
8165	child *d12nodeT   ///< Child node
8166	data  interface{} ///< Data Id or Ptr
8167}
8168
8169/// d12nodeT for each branch level
8170type d12nodeT struct {
8171	count  int                     ///< Count
8172	level  int                     ///< Leaf is zero, others positive
8173	branch [d12maxNodes]d12branchT ///< Branch
8174}
8175
8176func (node *d12nodeT) isInternalNode() bool {
8177	return (node.level > 0) // Not a leaf, but a internal node
8178}
8179func (node *d12nodeT) isLeaf() bool {
8180	return (node.level == 0) // A leaf, contains data
8181}
8182
8183/// A link list of nodes for reinsertion after a delete operation
8184type d12listNodeT struct {
8185	next *d12listNodeT ///< Next in list
8186	node *d12nodeT     ///< Node
8187}
8188
8189const d12notTaken = -1 // indicates that position
8190
8191/// Variables for finding a split partition
8192type d12partitionVarsT struct {
8193	partition [d12maxNodes + 1]int
8194	total     int
8195	minFill   int
8196	count     [2]int
8197	cover     [2]d12rectT
8198	area      [2]float64
8199
8200	branchBuf      [d12maxNodes + 1]d12branchT
8201	branchCount    int
8202	coverSplit     d12rectT
8203	coverSplitArea float64
8204}
8205
8206func d12New() *d12RTree {
8207	// We only support machine word size simple data type eg. integer index or object pointer.
8208	// Since we are storing as union with non data branch
8209	return &d12RTree{
8210		root: &d12nodeT{},
8211	}
8212}
8213
8214/// Insert entry
8215/// \param a_min Min of bounding rect
8216/// \param a_max Max of bounding rect
8217/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
8218func (tr *d12RTree) Insert(min, max [d12numDims]float64, dataId interface{}) {
8219	var branch d12branchT
8220	branch.data = dataId
8221	for axis := 0; axis < d12numDims; axis++ {
8222		branch.rect.min[axis] = min[axis]
8223		branch.rect.max[axis] = max[axis]
8224	}
8225	d12insertRect(&branch, &tr.root, 0)
8226}
8227
8228/// Remove entry
8229/// \param a_min Min of bounding rect
8230/// \param a_max Max of bounding rect
8231/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
8232func (tr *d12RTree) Remove(min, max [d12numDims]float64, dataId interface{}) {
8233	var rect d12rectT
8234	for axis := 0; axis < d12numDims; axis++ {
8235		rect.min[axis] = min[axis]
8236		rect.max[axis] = max[axis]
8237	}
8238	d12removeRect(&rect, dataId, &tr.root)
8239}
8240
8241/// Find all within d12search rectangle
8242/// \param a_min Min of d12search bounding rect
8243/// \param a_max Max of d12search bounding rect
8244/// \param a_searchResult d12search result array.  Caller should set grow size. Function will reset, not append to array.
8245/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
8246/// \param a_context User context to pass as parameter to a_resultCallback
8247/// \return Returns the number of entries found
8248func (tr *d12RTree) Search(min, max [d12numDims]float64, resultCallback func(data interface{}) bool) int {
8249	var rect d12rectT
8250	for axis := 0; axis < d12numDims; axis++ {
8251		rect.min[axis] = min[axis]
8252		rect.max[axis] = max[axis]
8253	}
8254	foundCount, _ := d12search(tr.root, rect, 0, resultCallback)
8255	return foundCount
8256}
8257
8258/// Count the data elements in this container.  This is slow as no internal counter is maintained.
8259func (tr *d12RTree) Count() int {
8260	var count int
8261	d12countRec(tr.root, &count)
8262	return count
8263}
8264
8265/// Remove all entries from tree
8266func (tr *d12RTree) RemoveAll() {
8267	// Delete all existing nodes
8268	tr.root = &d12nodeT{}
8269}
8270
8271func d12countRec(node *d12nodeT, count *int) {
8272	if node.isInternalNode() { // not a leaf node
8273		for index := 0; index < node.count; index++ {
8274			d12countRec(node.branch[index].child, count)
8275		}
8276	} else { // A leaf node
8277		*count += node.count
8278	}
8279}
8280
8281// Inserts a new data rectangle into the index structure.
8282// Recursively descends tree, propagates splits back up.
8283// Returns 0 if node was not split.  Old node updated.
8284// If node was split, returns 1 and sets the pointer pointed to by
8285// new_node to point to the new node.  Old node updated to become one of two.
8286// The level argument specifies the number of steps up from the leaf
8287// level to insert; e.g. a data rectangle goes in at level = 0.
8288func d12insertRectRec(branch *d12branchT, node *d12nodeT, newNode **d12nodeT, level int) bool {
8289	// recurse until we reach the correct level for the new record. data records
8290	// will always be called with a_level == 0 (leaf)
8291	if node.level > level {
8292		// Still above level for insertion, go down tree recursively
8293		var otherNode *d12nodeT
8294		//var newBranch d12branchT
8295
8296		// find the optimal branch for this record
8297		index := d12pickBranch(&branch.rect, node)
8298
8299		// recursively insert this record into the picked branch
8300		childWasSplit := d12insertRectRec(branch, node.branch[index].child, &otherNode, level)
8301
8302		if !childWasSplit {
8303			// Child was not split. Merge the bounding box of the new record with the
8304			// existing bounding box
8305			node.branch[index].rect = d12combineRect(&branch.rect, &(node.branch[index].rect))
8306			return false
8307		} else {
8308			// Child was split. The old branches are now re-partitioned to two nodes
8309			// so we have to re-calculate the bounding boxes of each node
8310			node.branch[index].rect = d12nodeCover(node.branch[index].child)
8311			var newBranch d12branchT
8312			newBranch.child = otherNode
8313			newBranch.rect = d12nodeCover(otherNode)
8314
8315			// The old node is already a child of a_node. Now add the newly-created
8316			// node to a_node as well. a_node might be split because of that.
8317			return d12addBranch(&newBranch, node, newNode)
8318		}
8319	} else if node.level == level {
8320		// We have reached level for insertion. Add rect, split if necessary
8321		return d12addBranch(branch, node, newNode)
8322	} else {
8323		// Should never occur
8324		return false
8325	}
8326}
8327
8328// Insert a data rectangle into an index structure.
8329// d12insertRect provides for splitting the root;
8330// returns 1 if root was split, 0 if it was not.
8331// The level argument specifies the number of steps up from the leaf
8332// level to insert; e.g. a data rectangle goes in at level = 0.
8333// InsertRect2 does the recursion.
8334//
8335func d12insertRect(branch *d12branchT, root **d12nodeT, level int) bool {
8336	var newNode *d12nodeT
8337
8338	if d12insertRectRec(branch, *root, &newNode, level) { // Root split
8339
8340		// Grow tree taller and new root
8341		newRoot := &d12nodeT{}
8342		newRoot.level = (*root).level + 1
8343
8344		var newBranch d12branchT
8345
8346		// add old root node as a child of the new root
8347		newBranch.rect = d12nodeCover(*root)
8348		newBranch.child = *root
8349		d12addBranch(&newBranch, newRoot, nil)
8350
8351		// add the split node as a child of the new root
8352		newBranch.rect = d12nodeCover(newNode)
8353		newBranch.child = newNode
8354		d12addBranch(&newBranch, newRoot, nil)
8355
8356		// set the new root as the root node
8357		*root = newRoot
8358
8359		return true
8360	}
8361	return false
8362}
8363
8364// Find the smallest rectangle that includes all rectangles in branches of a node.
8365func d12nodeCover(node *d12nodeT) d12rectT {
8366	rect := node.branch[0].rect
8367	for index := 1; index < node.count; index++ {
8368		rect = d12combineRect(&rect, &(node.branch[index].rect))
8369	}
8370	return rect
8371}
8372
8373// Add a branch to a node.  Split the node if necessary.
8374// Returns 0 if node not split.  Old node updated.
8375// Returns 1 if node split, sets *new_node to address of new node.
8376// Old node updated, becomes one of two.
8377func d12addBranch(branch *d12branchT, node *d12nodeT, newNode **d12nodeT) bool {
8378	if node.count < d12maxNodes { // Split won't be necessary
8379		node.branch[node.count] = *branch
8380		node.count++
8381		return false
8382	} else {
8383		d12splitNode(node, branch, newNode)
8384		return true
8385	}
8386}
8387
8388// Disconnect a dependent node.
8389// Caller must return (or stop using iteration index) after this as count has changed
8390func d12disconnectBranch(node *d12nodeT, index int) {
8391	// Remove element by swapping with the last element to prevent gaps in array
8392	node.branch[index] = node.branch[node.count-1]
8393	node.branch[node.count-1].data = nil
8394	node.branch[node.count-1].child = nil
8395	node.count--
8396}
8397
8398// Pick a branch.  Pick the one that will need the smallest increase
8399// in area to accomodate the new rectangle.  This will result in the
8400// least total area for the covering rectangles in the current node.
8401// In case of a tie, pick the one which was smaller before, to get
8402// the best resolution when searching.
8403func d12pickBranch(rect *d12rectT, node *d12nodeT) int {
8404	var firstTime bool = true
8405	var increase float64
8406	var bestIncr float64 = -1
8407	var area float64
8408	var bestArea float64
8409	var best int
8410	var tempRect d12rectT
8411
8412	for index := 0; index < node.count; index++ {
8413		curRect := &node.branch[index].rect
8414		area = d12calcRectVolume(curRect)
8415		tempRect = d12combineRect(rect, curRect)
8416		increase = d12calcRectVolume(&tempRect) - area
8417		if (increase < bestIncr) || firstTime {
8418			best = index
8419			bestArea = area
8420			bestIncr = increase
8421			firstTime = false
8422		} else if (increase == bestIncr) && (area < bestArea) {
8423			best = index
8424			bestArea = area
8425			bestIncr = increase
8426		}
8427	}
8428	return best
8429}
8430
8431// Combine two rectangles into larger one containing both
8432func d12combineRect(rectA, rectB *d12rectT) d12rectT {
8433	var newRect d12rectT
8434
8435	for index := 0; index < d12numDims; index++ {
8436		newRect.min[index] = d12fmin(rectA.min[index], rectB.min[index])
8437		newRect.max[index] = d12fmax(rectA.max[index], rectB.max[index])
8438	}
8439
8440	return newRect
8441}
8442
8443// Split a node.
8444// Divides the nodes branches and the extra one between two nodes.
8445// Old node is one of the new ones, and one really new one is created.
8446// Tries more than one method for choosing a partition, uses best result.
8447func d12splitNode(node *d12nodeT, branch *d12branchT, newNode **d12nodeT) {
8448	// Could just use local here, but member or external is faster since it is reused
8449	var localVars d12partitionVarsT
8450	parVars := &localVars
8451
8452	// Load all the branches into a buffer, initialize old node
8453	d12getBranches(node, branch, parVars)
8454
8455	// Find partition
8456	d12choosePartition(parVars, d12minNodes)
8457
8458	// Create a new node to hold (about) half of the branches
8459	*newNode = &d12nodeT{}
8460	(*newNode).level = node.level
8461
8462	// Put branches from buffer into 2 nodes according to the chosen partition
8463	node.count = 0
8464	d12loadNodes(node, *newNode, parVars)
8465}
8466
8467// Calculate the n-dimensional volume of a rectangle
8468func d12rectVolume(rect *d12rectT) float64 {
8469	var volume float64 = 1
8470	for index := 0; index < d12numDims; index++ {
8471		volume *= rect.max[index] - rect.min[index]
8472	}
8473	return volume
8474}
8475
8476// The exact volume of the bounding sphere for the given d12rectT
8477func d12rectSphericalVolume(rect *d12rectT) float64 {
8478	var sumOfSquares float64 = 0
8479	var radius float64
8480
8481	for index := 0; index < d12numDims; index++ {
8482		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
8483		sumOfSquares += halfExtent * halfExtent
8484	}
8485
8486	radius = math.Sqrt(sumOfSquares)
8487
8488	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
8489	if d12numDims == 5 {
8490		return (radius * radius * radius * radius * radius * d12unitSphereVolume)
8491	} else if d12numDims == 4 {
8492		return (radius * radius * radius * radius * d12unitSphereVolume)
8493	} else if d12numDims == 3 {
8494		return (radius * radius * radius * d12unitSphereVolume)
8495	} else if d12numDims == 2 {
8496		return (radius * radius * d12unitSphereVolume)
8497	} else {
8498		return (math.Pow(radius, d12numDims) * d12unitSphereVolume)
8499	}
8500}
8501
8502// Use one of the methods to calculate retangle volume
8503func d12calcRectVolume(rect *d12rectT) float64 {
8504	if d12useSphericalVolume {
8505		return d12rectSphericalVolume(rect) // Slower but helps certain merge cases
8506	} else { // RTREE_USE_SPHERICAL_VOLUME
8507		return d12rectVolume(rect) // Faster but can cause poor merges
8508	} // RTREE_USE_SPHERICAL_VOLUME
8509}
8510
8511// Load branch buffer with branches from full node plus the extra branch.
8512func d12getBranches(node *d12nodeT, branch *d12branchT, parVars *d12partitionVarsT) {
8513	// Load the branch buffer
8514	for index := 0; index < d12maxNodes; index++ {
8515		parVars.branchBuf[index] = node.branch[index]
8516	}
8517	parVars.branchBuf[d12maxNodes] = *branch
8518	parVars.branchCount = d12maxNodes + 1
8519
8520	// Calculate rect containing all in the set
8521	parVars.coverSplit = parVars.branchBuf[0].rect
8522	for index := 1; index < d12maxNodes+1; index++ {
8523		parVars.coverSplit = d12combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
8524	}
8525	parVars.coverSplitArea = d12calcRectVolume(&parVars.coverSplit)
8526}
8527
8528// Method #0 for choosing a partition:
8529// As the seeds for the two groups, pick the two rects that would waste the
8530// most area if covered by a single rectangle, i.e. evidently the worst pair
8531// to have in the same group.
8532// Of the remaining, one at a time is chosen to be put in one of the two groups.
8533// The one chosen is the one with the greatest difference in area expansion
8534// depending on which group - the rect most strongly attracted to one group
8535// and repelled from the other.
8536// If one group gets too full (more would force other group to violate min
8537// fill requirement) then other group gets the rest.
8538// These last are the ones that can go in either group most easily.
8539func d12choosePartition(parVars *d12partitionVarsT, minFill int) {
8540	var biggestDiff float64
8541	var group, chosen, betterGroup int
8542
8543	d12initParVars(parVars, parVars.branchCount, minFill)
8544	d12pickSeeds(parVars)
8545
8546	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
8547		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
8548		(parVars.count[1] < (parVars.total - parVars.minFill)) {
8549		biggestDiff = -1
8550		for index := 0; index < parVars.total; index++ {
8551			if d12notTaken == parVars.partition[index] {
8552				curRect := &parVars.branchBuf[index].rect
8553				rect0 := d12combineRect(curRect, &parVars.cover[0])
8554				rect1 := d12combineRect(curRect, &parVars.cover[1])
8555				growth0 := d12calcRectVolume(&rect0) - parVars.area[0]
8556				growth1 := d12calcRectVolume(&rect1) - parVars.area[1]
8557				diff := growth1 - growth0
8558				if diff >= 0 {
8559					group = 0
8560				} else {
8561					group = 1
8562					diff = -diff
8563				}
8564
8565				if diff > biggestDiff {
8566					biggestDiff = diff
8567					chosen = index
8568					betterGroup = group
8569				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
8570					chosen = index
8571					betterGroup = group
8572				}
8573			}
8574		}
8575		d12classify(chosen, betterGroup, parVars)
8576	}
8577
8578	// If one group too full, put remaining rects in the other
8579	if (parVars.count[0] + parVars.count[1]) < parVars.total {
8580		if parVars.count[0] >= parVars.total-parVars.minFill {
8581			group = 1
8582		} else {
8583			group = 0
8584		}
8585		for index := 0; index < parVars.total; index++ {
8586			if d12notTaken == parVars.partition[index] {
8587				d12classify(index, group, parVars)
8588			}
8589		}
8590	}
8591}
8592
8593// Copy branches from the buffer into two nodes according to the partition.
8594func d12loadNodes(nodeA, nodeB *d12nodeT, parVars *d12partitionVarsT) {
8595	for index := 0; index < parVars.total; index++ {
8596		targetNodeIndex := parVars.partition[index]
8597		targetNodes := []*d12nodeT{nodeA, nodeB}
8598
8599		// It is assured that d12addBranch here will not cause a node split.
8600		d12addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
8601	}
8602}
8603
8604// Initialize a d12partitionVarsT structure.
8605func d12initParVars(parVars *d12partitionVarsT, maxRects, minFill int) {
8606	parVars.count[0] = 0
8607	parVars.count[1] = 0
8608	parVars.area[0] = 0
8609	parVars.area[1] = 0
8610	parVars.total = maxRects
8611	parVars.minFill = minFill
8612	for index := 0; index < maxRects; index++ {
8613		parVars.partition[index] = d12notTaken
8614	}
8615}
8616
8617func d12pickSeeds(parVars *d12partitionVarsT) {
8618	var seed0, seed1 int
8619	var worst, waste float64
8620	var area [d12maxNodes + 1]float64
8621
8622	for index := 0; index < parVars.total; index++ {
8623		area[index] = d12calcRectVolume(&parVars.branchBuf[index].rect)
8624	}
8625
8626	worst = -parVars.coverSplitArea - 1
8627	for indexA := 0; indexA < parVars.total-1; indexA++ {
8628		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
8629			oneRect := d12combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
8630			waste = d12calcRectVolume(&oneRect) - area[indexA] - area[indexB]
8631			if waste > worst {
8632				worst = waste
8633				seed0 = indexA
8634				seed1 = indexB
8635			}
8636		}
8637	}
8638
8639	d12classify(seed0, 0, parVars)
8640	d12classify(seed1, 1, parVars)
8641}
8642
8643// Put a branch in one of the groups.
8644func d12classify(index, group int, parVars *d12partitionVarsT) {
8645	parVars.partition[index] = group
8646
8647	// Calculate combined rect
8648	if parVars.count[group] == 0 {
8649		parVars.cover[group] = parVars.branchBuf[index].rect
8650	} else {
8651		parVars.cover[group] = d12combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
8652	}
8653
8654	// Calculate volume of combined rect
8655	parVars.area[group] = d12calcRectVolume(&parVars.cover[group])
8656
8657	parVars.count[group]++
8658}
8659
8660// Delete a data rectangle from an index structure.
8661// Pass in a pointer to a d12rectT, the tid of the record, ptr to ptr to root node.
8662// Returns 1 if record not found, 0 if success.
8663// d12removeRect provides for eliminating the root.
8664func d12removeRect(rect *d12rectT, id interface{}, root **d12nodeT) bool {
8665	var reInsertList *d12listNodeT
8666
8667	if !d12removeRectRec(rect, id, *root, &reInsertList) {
8668		// Found and deleted a data item
8669		// Reinsert any branches from eliminated nodes
8670		for reInsertList != nil {
8671			tempNode := reInsertList.node
8672
8673			for index := 0; index < tempNode.count; index++ {
8674				// TODO go over this code. should I use (tempNode->m_level - 1)?
8675				d12insertRect(&tempNode.branch[index], root, tempNode.level)
8676			}
8677			reInsertList = reInsertList.next
8678		}
8679
8680		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
8681		// if with while? In case there is a whole branch of redundant roots...
8682		if (*root).count == 1 && (*root).isInternalNode() {
8683			tempNode := (*root).branch[0].child
8684			*root = tempNode
8685		}
8686		return false
8687	} else {
8688		return true
8689	}
8690}
8691
8692// Delete a rectangle from non-root part of an index structure.
8693// Called by d12removeRect.  Descends tree recursively,
8694// merges branches on the way back up.
8695// Returns 1 if record not found, 0 if success.
8696func d12removeRectRec(rect *d12rectT, id interface{}, node *d12nodeT, listNode **d12listNodeT) bool {
8697	if node.isInternalNode() { // not a leaf node
8698		for index := 0; index < node.count; index++ {
8699			if d12overlap(*rect, node.branch[index].rect) {
8700				if !d12removeRectRec(rect, id, node.branch[index].child, listNode) {
8701					if node.branch[index].child.count >= d12minNodes {
8702						// child removed, just resize parent rect
8703						node.branch[index].rect = d12nodeCover(node.branch[index].child)
8704					} else {
8705						// child removed, not enough entries in node, eliminate node
8706						d12reInsert(node.branch[index].child, listNode)
8707						d12disconnectBranch(node, index) // Must return after this call as count has changed
8708					}
8709					return false
8710				}
8711			}
8712		}
8713		return true
8714	} else { // A leaf node
8715		for index := 0; index < node.count; index++ {
8716			if node.branch[index].data == id {
8717				d12disconnectBranch(node, index) // Must return after this call as count has changed
8718				return false
8719			}
8720		}
8721		return true
8722	}
8723}
8724
8725// Decide whether two rectangles d12overlap.
8726func d12overlap(rectA, rectB d12rectT) bool {
8727	for index := 0; index < d12numDims; index++ {
8728		if rectA.min[index] > rectB.max[index] ||
8729			rectB.min[index] > rectA.max[index] {
8730			return false
8731		}
8732	}
8733	return true
8734}
8735
8736// Add a node to the reinsertion list.  All its branches will later
8737// be reinserted into the index structure.
8738func d12reInsert(node *d12nodeT, listNode **d12listNodeT) {
8739	newListNode := &d12listNodeT{}
8740	newListNode.node = node
8741	newListNode.next = *listNode
8742	*listNode = newListNode
8743}
8744
8745// d12search in an index tree or subtree for all data retangles that d12overlap the argument rectangle.
8746func d12search(node *d12nodeT, rect d12rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
8747	if node.isInternalNode() {
8748		// This is an internal node in the tree
8749		for index := 0; index < node.count; index++ {
8750			if d12overlap(rect, node.branch[index].rect) {
8751				var ok bool
8752				foundCount, ok = d12search(node.branch[index].child, rect, foundCount, resultCallback)
8753				if !ok {
8754					// The callback indicated to stop searching
8755					return foundCount, false
8756				}
8757			}
8758		}
8759	} else {
8760		// This is a leaf node
8761		for index := 0; index < node.count; index++ {
8762			if d12overlap(rect, node.branch[index].rect) {
8763				id := node.branch[index].data
8764				foundCount++
8765				if !resultCallback(id) {
8766					return foundCount, false // Don't continue searching
8767				}
8768
8769			}
8770		}
8771	}
8772	return foundCount, true // Continue searching
8773}
8774
8775func d13fmin(a, b float64) float64 {
8776	if a < b {
8777		return a
8778	}
8779	return b
8780}
8781func d13fmax(a, b float64) float64 {
8782	if a > b {
8783		return a
8784	}
8785	return b
8786}
8787
8788const (
8789	d13numDims            = 13
8790	d13maxNodes           = 8
8791	d13minNodes           = d13maxNodes / 2
8792	d13useSphericalVolume = true // Better split classification, may be slower on some systems
8793)
8794
8795var d13unitSphereVolume = []float64{
8796	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
8797	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
8798	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
8799	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
8800	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
8801	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
8802	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
8803}[d13numDims]
8804
8805type d13RTree struct {
8806	root *d13nodeT ///< Root of tree
8807}
8808
8809/// Minimal bounding rectangle (n-dimensional)
8810type d13rectT struct {
8811	min [d13numDims]float64 ///< Min dimensions of bounding box
8812	max [d13numDims]float64 ///< Max dimensions of bounding box
8813}
8814
8815/// May be data or may be another subtree
8816/// The parents level determines this.
8817/// If the parents level is 0, then this is data
8818type d13branchT struct {
8819	rect  d13rectT    ///< Bounds
8820	child *d13nodeT   ///< Child node
8821	data  interface{} ///< Data Id or Ptr
8822}
8823
8824/// d13nodeT for each branch level
8825type d13nodeT struct {
8826	count  int                     ///< Count
8827	level  int                     ///< Leaf is zero, others positive
8828	branch [d13maxNodes]d13branchT ///< Branch
8829}
8830
8831func (node *d13nodeT) isInternalNode() bool {
8832	return (node.level > 0) // Not a leaf, but a internal node
8833}
8834func (node *d13nodeT) isLeaf() bool {
8835	return (node.level == 0) // A leaf, contains data
8836}
8837
8838/// A link list of nodes for reinsertion after a delete operation
8839type d13listNodeT struct {
8840	next *d13listNodeT ///< Next in list
8841	node *d13nodeT     ///< Node
8842}
8843
8844const d13notTaken = -1 // indicates that position
8845
8846/// Variables for finding a split partition
8847type d13partitionVarsT struct {
8848	partition [d13maxNodes + 1]int
8849	total     int
8850	minFill   int
8851	count     [2]int
8852	cover     [2]d13rectT
8853	area      [2]float64
8854
8855	branchBuf      [d13maxNodes + 1]d13branchT
8856	branchCount    int
8857	coverSplit     d13rectT
8858	coverSplitArea float64
8859}
8860
8861func d13New() *d13RTree {
8862	// We only support machine word size simple data type eg. integer index or object pointer.
8863	// Since we are storing as union with non data branch
8864	return &d13RTree{
8865		root: &d13nodeT{},
8866	}
8867}
8868
8869/// Insert entry
8870/// \param a_min Min of bounding rect
8871/// \param a_max Max of bounding rect
8872/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
8873func (tr *d13RTree) Insert(min, max [d13numDims]float64, dataId interface{}) {
8874	var branch d13branchT
8875	branch.data = dataId
8876	for axis := 0; axis < d13numDims; axis++ {
8877		branch.rect.min[axis] = min[axis]
8878		branch.rect.max[axis] = max[axis]
8879	}
8880	d13insertRect(&branch, &tr.root, 0)
8881}
8882
8883/// Remove entry
8884/// \param a_min Min of bounding rect
8885/// \param a_max Max of bounding rect
8886/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
8887func (tr *d13RTree) Remove(min, max [d13numDims]float64, dataId interface{}) {
8888	var rect d13rectT
8889	for axis := 0; axis < d13numDims; axis++ {
8890		rect.min[axis] = min[axis]
8891		rect.max[axis] = max[axis]
8892	}
8893	d13removeRect(&rect, dataId, &tr.root)
8894}
8895
8896/// Find all within d13search rectangle
8897/// \param a_min Min of d13search bounding rect
8898/// \param a_max Max of d13search bounding rect
8899/// \param a_searchResult d13search result array.  Caller should set grow size. Function will reset, not append to array.
8900/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
8901/// \param a_context User context to pass as parameter to a_resultCallback
8902/// \return Returns the number of entries found
8903func (tr *d13RTree) Search(min, max [d13numDims]float64, resultCallback func(data interface{}) bool) int {
8904	var rect d13rectT
8905	for axis := 0; axis < d13numDims; axis++ {
8906		rect.min[axis] = min[axis]
8907		rect.max[axis] = max[axis]
8908	}
8909	foundCount, _ := d13search(tr.root, rect, 0, resultCallback)
8910	return foundCount
8911}
8912
8913/// Count the data elements in this container.  This is slow as no internal counter is maintained.
8914func (tr *d13RTree) Count() int {
8915	var count int
8916	d13countRec(tr.root, &count)
8917	return count
8918}
8919
8920/// Remove all entries from tree
8921func (tr *d13RTree) RemoveAll() {
8922	// Delete all existing nodes
8923	tr.root = &d13nodeT{}
8924}
8925
8926func d13countRec(node *d13nodeT, count *int) {
8927	if node.isInternalNode() { // not a leaf node
8928		for index := 0; index < node.count; index++ {
8929			d13countRec(node.branch[index].child, count)
8930		}
8931	} else { // A leaf node
8932		*count += node.count
8933	}
8934}
8935
8936// Inserts a new data rectangle into the index structure.
8937// Recursively descends tree, propagates splits back up.
8938// Returns 0 if node was not split.  Old node updated.
8939// If node was split, returns 1 and sets the pointer pointed to by
8940// new_node to point to the new node.  Old node updated to become one of two.
8941// The level argument specifies the number of steps up from the leaf
8942// level to insert; e.g. a data rectangle goes in at level = 0.
8943func d13insertRectRec(branch *d13branchT, node *d13nodeT, newNode **d13nodeT, level int) bool {
8944	// recurse until we reach the correct level for the new record. data records
8945	// will always be called with a_level == 0 (leaf)
8946	if node.level > level {
8947		// Still above level for insertion, go down tree recursively
8948		var otherNode *d13nodeT
8949		//var newBranch d13branchT
8950
8951		// find the optimal branch for this record
8952		index := d13pickBranch(&branch.rect, node)
8953
8954		// recursively insert this record into the picked branch
8955		childWasSplit := d13insertRectRec(branch, node.branch[index].child, &otherNode, level)
8956
8957		if !childWasSplit {
8958			// Child was not split. Merge the bounding box of the new record with the
8959			// existing bounding box
8960			node.branch[index].rect = d13combineRect(&branch.rect, &(node.branch[index].rect))
8961			return false
8962		} else {
8963			// Child was split. The old branches are now re-partitioned to two nodes
8964			// so we have to re-calculate the bounding boxes of each node
8965			node.branch[index].rect = d13nodeCover(node.branch[index].child)
8966			var newBranch d13branchT
8967			newBranch.child = otherNode
8968			newBranch.rect = d13nodeCover(otherNode)
8969
8970			// The old node is already a child of a_node. Now add the newly-created
8971			// node to a_node as well. a_node might be split because of that.
8972			return d13addBranch(&newBranch, node, newNode)
8973		}
8974	} else if node.level == level {
8975		// We have reached level for insertion. Add rect, split if necessary
8976		return d13addBranch(branch, node, newNode)
8977	} else {
8978		// Should never occur
8979		return false
8980	}
8981}
8982
8983// Insert a data rectangle into an index structure.
8984// d13insertRect provides for splitting the root;
8985// returns 1 if root was split, 0 if it was not.
8986// The level argument specifies the number of steps up from the leaf
8987// level to insert; e.g. a data rectangle goes in at level = 0.
8988// InsertRect2 does the recursion.
8989//
8990func d13insertRect(branch *d13branchT, root **d13nodeT, level int) bool {
8991	var newNode *d13nodeT
8992
8993	if d13insertRectRec(branch, *root, &newNode, level) { // Root split
8994
8995		// Grow tree taller and new root
8996		newRoot := &d13nodeT{}
8997		newRoot.level = (*root).level + 1
8998
8999		var newBranch d13branchT
9000
9001		// add old root node as a child of the new root
9002		newBranch.rect = d13nodeCover(*root)
9003		newBranch.child = *root
9004		d13addBranch(&newBranch, newRoot, nil)
9005
9006		// add the split node as a child of the new root
9007		newBranch.rect = d13nodeCover(newNode)
9008		newBranch.child = newNode
9009		d13addBranch(&newBranch, newRoot, nil)
9010
9011		// set the new root as the root node
9012		*root = newRoot
9013
9014		return true
9015	}
9016	return false
9017}
9018
9019// Find the smallest rectangle that includes all rectangles in branches of a node.
9020func d13nodeCover(node *d13nodeT) d13rectT {
9021	rect := node.branch[0].rect
9022	for index := 1; index < node.count; index++ {
9023		rect = d13combineRect(&rect, &(node.branch[index].rect))
9024	}
9025	return rect
9026}
9027
9028// Add a branch to a node.  Split the node if necessary.
9029// Returns 0 if node not split.  Old node updated.
9030// Returns 1 if node split, sets *new_node to address of new node.
9031// Old node updated, becomes one of two.
9032func d13addBranch(branch *d13branchT, node *d13nodeT, newNode **d13nodeT) bool {
9033	if node.count < d13maxNodes { // Split won't be necessary
9034		node.branch[node.count] = *branch
9035		node.count++
9036		return false
9037	} else {
9038		d13splitNode(node, branch, newNode)
9039		return true
9040	}
9041}
9042
9043// Disconnect a dependent node.
9044// Caller must return (or stop using iteration index) after this as count has changed
9045func d13disconnectBranch(node *d13nodeT, index int) {
9046	// Remove element by swapping with the last element to prevent gaps in array
9047	node.branch[index] = node.branch[node.count-1]
9048	node.branch[node.count-1].data = nil
9049	node.branch[node.count-1].child = nil
9050	node.count--
9051}
9052
9053// Pick a branch.  Pick the one that will need the smallest increase
9054// in area to accomodate the new rectangle.  This will result in the
9055// least total area for the covering rectangles in the current node.
9056// In case of a tie, pick the one which was smaller before, to get
9057// the best resolution when searching.
9058func d13pickBranch(rect *d13rectT, node *d13nodeT) int {
9059	var firstTime bool = true
9060	var increase float64
9061	var bestIncr float64 = -1
9062	var area float64
9063	var bestArea float64
9064	var best int
9065	var tempRect d13rectT
9066
9067	for index := 0; index < node.count; index++ {
9068		curRect := &node.branch[index].rect
9069		area = d13calcRectVolume(curRect)
9070		tempRect = d13combineRect(rect, curRect)
9071		increase = d13calcRectVolume(&tempRect) - area
9072		if (increase < bestIncr) || firstTime {
9073			best = index
9074			bestArea = area
9075			bestIncr = increase
9076			firstTime = false
9077		} else if (increase == bestIncr) && (area < bestArea) {
9078			best = index
9079			bestArea = area
9080			bestIncr = increase
9081		}
9082	}
9083	return best
9084}
9085
9086// Combine two rectangles into larger one containing both
9087func d13combineRect(rectA, rectB *d13rectT) d13rectT {
9088	var newRect d13rectT
9089
9090	for index := 0; index < d13numDims; index++ {
9091		newRect.min[index] = d13fmin(rectA.min[index], rectB.min[index])
9092		newRect.max[index] = d13fmax(rectA.max[index], rectB.max[index])
9093	}
9094
9095	return newRect
9096}
9097
9098// Split a node.
9099// Divides the nodes branches and the extra one between two nodes.
9100// Old node is one of the new ones, and one really new one is created.
9101// Tries more than one method for choosing a partition, uses best result.
9102func d13splitNode(node *d13nodeT, branch *d13branchT, newNode **d13nodeT) {
9103	// Could just use local here, but member or external is faster since it is reused
9104	var localVars d13partitionVarsT
9105	parVars := &localVars
9106
9107	// Load all the branches into a buffer, initialize old node
9108	d13getBranches(node, branch, parVars)
9109
9110	// Find partition
9111	d13choosePartition(parVars, d13minNodes)
9112
9113	// Create a new node to hold (about) half of the branches
9114	*newNode = &d13nodeT{}
9115	(*newNode).level = node.level
9116
9117	// Put branches from buffer into 2 nodes according to the chosen partition
9118	node.count = 0
9119	d13loadNodes(node, *newNode, parVars)
9120}
9121
9122// Calculate the n-dimensional volume of a rectangle
9123func d13rectVolume(rect *d13rectT) float64 {
9124	var volume float64 = 1
9125	for index := 0; index < d13numDims; index++ {
9126		volume *= rect.max[index] - rect.min[index]
9127	}
9128	return volume
9129}
9130
9131// The exact volume of the bounding sphere for the given d13rectT
9132func d13rectSphericalVolume(rect *d13rectT) float64 {
9133	var sumOfSquares float64 = 0
9134	var radius float64
9135
9136	for index := 0; index < d13numDims; index++ {
9137		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
9138		sumOfSquares += halfExtent * halfExtent
9139	}
9140
9141	radius = math.Sqrt(sumOfSquares)
9142
9143	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
9144	if d13numDims == 5 {
9145		return (radius * radius * radius * radius * radius * d13unitSphereVolume)
9146	} else if d13numDims == 4 {
9147		return (radius * radius * radius * radius * d13unitSphereVolume)
9148	} else if d13numDims == 3 {
9149		return (radius * radius * radius * d13unitSphereVolume)
9150	} else if d13numDims == 2 {
9151		return (radius * radius * d13unitSphereVolume)
9152	} else {
9153		return (math.Pow(radius, d13numDims) * d13unitSphereVolume)
9154	}
9155}
9156
9157// Use one of the methods to calculate retangle volume
9158func d13calcRectVolume(rect *d13rectT) float64 {
9159	if d13useSphericalVolume {
9160		return d13rectSphericalVolume(rect) // Slower but helps certain merge cases
9161	} else { // RTREE_USE_SPHERICAL_VOLUME
9162		return d13rectVolume(rect) // Faster but can cause poor merges
9163	} // RTREE_USE_SPHERICAL_VOLUME
9164}
9165
9166// Load branch buffer with branches from full node plus the extra branch.
9167func d13getBranches(node *d13nodeT, branch *d13branchT, parVars *d13partitionVarsT) {
9168	// Load the branch buffer
9169	for index := 0; index < d13maxNodes; index++ {
9170		parVars.branchBuf[index] = node.branch[index]
9171	}
9172	parVars.branchBuf[d13maxNodes] = *branch
9173	parVars.branchCount = d13maxNodes + 1
9174
9175	// Calculate rect containing all in the set
9176	parVars.coverSplit = parVars.branchBuf[0].rect
9177	for index := 1; index < d13maxNodes+1; index++ {
9178		parVars.coverSplit = d13combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
9179	}
9180	parVars.coverSplitArea = d13calcRectVolume(&parVars.coverSplit)
9181}
9182
9183// Method #0 for choosing a partition:
9184// As the seeds for the two groups, pick the two rects that would waste the
9185// most area if covered by a single rectangle, i.e. evidently the worst pair
9186// to have in the same group.
9187// Of the remaining, one at a time is chosen to be put in one of the two groups.
9188// The one chosen is the one with the greatest difference in area expansion
9189// depending on which group - the rect most strongly attracted to one group
9190// and repelled from the other.
9191// If one group gets too full (more would force other group to violate min
9192// fill requirement) then other group gets the rest.
9193// These last are the ones that can go in either group most easily.
9194func d13choosePartition(parVars *d13partitionVarsT, minFill int) {
9195	var biggestDiff float64
9196	var group, chosen, betterGroup int
9197
9198	d13initParVars(parVars, parVars.branchCount, minFill)
9199	d13pickSeeds(parVars)
9200
9201	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
9202		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
9203		(parVars.count[1] < (parVars.total - parVars.minFill)) {
9204		biggestDiff = -1
9205		for index := 0; index < parVars.total; index++ {
9206			if d13notTaken == parVars.partition[index] {
9207				curRect := &parVars.branchBuf[index].rect
9208				rect0 := d13combineRect(curRect, &parVars.cover[0])
9209				rect1 := d13combineRect(curRect, &parVars.cover[1])
9210				growth0 := d13calcRectVolume(&rect0) - parVars.area[0]
9211				growth1 := d13calcRectVolume(&rect1) - parVars.area[1]
9212				diff := growth1 - growth0
9213				if diff >= 0 {
9214					group = 0
9215				} else {
9216					group = 1
9217					diff = -diff
9218				}
9219
9220				if diff > biggestDiff {
9221					biggestDiff = diff
9222					chosen = index
9223					betterGroup = group
9224				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
9225					chosen = index
9226					betterGroup = group
9227				}
9228			}
9229		}
9230		d13classify(chosen, betterGroup, parVars)
9231	}
9232
9233	// If one group too full, put remaining rects in the other
9234	if (parVars.count[0] + parVars.count[1]) < parVars.total {
9235		if parVars.count[0] >= parVars.total-parVars.minFill {
9236			group = 1
9237		} else {
9238			group = 0
9239		}
9240		for index := 0; index < parVars.total; index++ {
9241			if d13notTaken == parVars.partition[index] {
9242				d13classify(index, group, parVars)
9243			}
9244		}
9245	}
9246}
9247
9248// Copy branches from the buffer into two nodes according to the partition.
9249func d13loadNodes(nodeA, nodeB *d13nodeT, parVars *d13partitionVarsT) {
9250	for index := 0; index < parVars.total; index++ {
9251		targetNodeIndex := parVars.partition[index]
9252		targetNodes := []*d13nodeT{nodeA, nodeB}
9253
9254		// It is assured that d13addBranch here will not cause a node split.
9255		d13addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
9256	}
9257}
9258
9259// Initialize a d13partitionVarsT structure.
9260func d13initParVars(parVars *d13partitionVarsT, maxRects, minFill int) {
9261	parVars.count[0] = 0
9262	parVars.count[1] = 0
9263	parVars.area[0] = 0
9264	parVars.area[1] = 0
9265	parVars.total = maxRects
9266	parVars.minFill = minFill
9267	for index := 0; index < maxRects; index++ {
9268		parVars.partition[index] = d13notTaken
9269	}
9270}
9271
9272func d13pickSeeds(parVars *d13partitionVarsT) {
9273	var seed0, seed1 int
9274	var worst, waste float64
9275	var area [d13maxNodes + 1]float64
9276
9277	for index := 0; index < parVars.total; index++ {
9278		area[index] = d13calcRectVolume(&parVars.branchBuf[index].rect)
9279	}
9280
9281	worst = -parVars.coverSplitArea - 1
9282	for indexA := 0; indexA < parVars.total-1; indexA++ {
9283		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
9284			oneRect := d13combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
9285			waste = d13calcRectVolume(&oneRect) - area[indexA] - area[indexB]
9286			if waste > worst {
9287				worst = waste
9288				seed0 = indexA
9289				seed1 = indexB
9290			}
9291		}
9292	}
9293
9294	d13classify(seed0, 0, parVars)
9295	d13classify(seed1, 1, parVars)
9296}
9297
9298// Put a branch in one of the groups.
9299func d13classify(index, group int, parVars *d13partitionVarsT) {
9300	parVars.partition[index] = group
9301
9302	// Calculate combined rect
9303	if parVars.count[group] == 0 {
9304		parVars.cover[group] = parVars.branchBuf[index].rect
9305	} else {
9306		parVars.cover[group] = d13combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
9307	}
9308
9309	// Calculate volume of combined rect
9310	parVars.area[group] = d13calcRectVolume(&parVars.cover[group])
9311
9312	parVars.count[group]++
9313}
9314
9315// Delete a data rectangle from an index structure.
9316// Pass in a pointer to a d13rectT, the tid of the record, ptr to ptr to root node.
9317// Returns 1 if record not found, 0 if success.
9318// d13removeRect provides for eliminating the root.
9319func d13removeRect(rect *d13rectT, id interface{}, root **d13nodeT) bool {
9320	var reInsertList *d13listNodeT
9321
9322	if !d13removeRectRec(rect, id, *root, &reInsertList) {
9323		// Found and deleted a data item
9324		// Reinsert any branches from eliminated nodes
9325		for reInsertList != nil {
9326			tempNode := reInsertList.node
9327
9328			for index := 0; index < tempNode.count; index++ {
9329				// TODO go over this code. should I use (tempNode->m_level - 1)?
9330				d13insertRect(&tempNode.branch[index], root, tempNode.level)
9331			}
9332			reInsertList = reInsertList.next
9333		}
9334
9335		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
9336		// if with while? In case there is a whole branch of redundant roots...
9337		if (*root).count == 1 && (*root).isInternalNode() {
9338			tempNode := (*root).branch[0].child
9339			*root = tempNode
9340		}
9341		return false
9342	} else {
9343		return true
9344	}
9345}
9346
9347// Delete a rectangle from non-root part of an index structure.
9348// Called by d13removeRect.  Descends tree recursively,
9349// merges branches on the way back up.
9350// Returns 1 if record not found, 0 if success.
9351func d13removeRectRec(rect *d13rectT, id interface{}, node *d13nodeT, listNode **d13listNodeT) bool {
9352	if node.isInternalNode() { // not a leaf node
9353		for index := 0; index < node.count; index++ {
9354			if d13overlap(*rect, node.branch[index].rect) {
9355				if !d13removeRectRec(rect, id, node.branch[index].child, listNode) {
9356					if node.branch[index].child.count >= d13minNodes {
9357						// child removed, just resize parent rect
9358						node.branch[index].rect = d13nodeCover(node.branch[index].child)
9359					} else {
9360						// child removed, not enough entries in node, eliminate node
9361						d13reInsert(node.branch[index].child, listNode)
9362						d13disconnectBranch(node, index) // Must return after this call as count has changed
9363					}
9364					return false
9365				}
9366			}
9367		}
9368		return true
9369	} else { // A leaf node
9370		for index := 0; index < node.count; index++ {
9371			if node.branch[index].data == id {
9372				d13disconnectBranch(node, index) // Must return after this call as count has changed
9373				return false
9374			}
9375		}
9376		return true
9377	}
9378}
9379
9380// Decide whether two rectangles d13overlap.
9381func d13overlap(rectA, rectB d13rectT) bool {
9382	for index := 0; index < d13numDims; index++ {
9383		if rectA.min[index] > rectB.max[index] ||
9384			rectB.min[index] > rectA.max[index] {
9385			return false
9386		}
9387	}
9388	return true
9389}
9390
9391// Add a node to the reinsertion list.  All its branches will later
9392// be reinserted into the index structure.
9393func d13reInsert(node *d13nodeT, listNode **d13listNodeT) {
9394	newListNode := &d13listNodeT{}
9395	newListNode.node = node
9396	newListNode.next = *listNode
9397	*listNode = newListNode
9398}
9399
9400// d13search in an index tree or subtree for all data retangles that d13overlap the argument rectangle.
9401func d13search(node *d13nodeT, rect d13rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
9402	if node.isInternalNode() {
9403		// This is an internal node in the tree
9404		for index := 0; index < node.count; index++ {
9405			if d13overlap(rect, node.branch[index].rect) {
9406				var ok bool
9407				foundCount, ok = d13search(node.branch[index].child, rect, foundCount, resultCallback)
9408				if !ok {
9409					// The callback indicated to stop searching
9410					return foundCount, false
9411				}
9412			}
9413		}
9414	} else {
9415		// This is a leaf node
9416		for index := 0; index < node.count; index++ {
9417			if d13overlap(rect, node.branch[index].rect) {
9418				id := node.branch[index].data
9419				foundCount++
9420				if !resultCallback(id) {
9421					return foundCount, false // Don't continue searching
9422				}
9423
9424			}
9425		}
9426	}
9427	return foundCount, true // Continue searching
9428}
9429
9430func d14fmin(a, b float64) float64 {
9431	if a < b {
9432		return a
9433	}
9434	return b
9435}
9436func d14fmax(a, b float64) float64 {
9437	if a > b {
9438		return a
9439	}
9440	return b
9441}
9442
9443const (
9444	d14numDims            = 14
9445	d14maxNodes           = 8
9446	d14minNodes           = d14maxNodes / 2
9447	d14useSphericalVolume = true // Better split classification, may be slower on some systems
9448)
9449
9450var d14unitSphereVolume = []float64{
9451	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
9452	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
9453	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
9454	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
9455	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
9456	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
9457	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
9458}[d14numDims]
9459
9460type d14RTree struct {
9461	root *d14nodeT ///< Root of tree
9462}
9463
9464/// Minimal bounding rectangle (n-dimensional)
9465type d14rectT struct {
9466	min [d14numDims]float64 ///< Min dimensions of bounding box
9467	max [d14numDims]float64 ///< Max dimensions of bounding box
9468}
9469
9470/// May be data or may be another subtree
9471/// The parents level determines this.
9472/// If the parents level is 0, then this is data
9473type d14branchT struct {
9474	rect  d14rectT    ///< Bounds
9475	child *d14nodeT   ///< Child node
9476	data  interface{} ///< Data Id or Ptr
9477}
9478
9479/// d14nodeT for each branch level
9480type d14nodeT struct {
9481	count  int                     ///< Count
9482	level  int                     ///< Leaf is zero, others positive
9483	branch [d14maxNodes]d14branchT ///< Branch
9484}
9485
9486func (node *d14nodeT) isInternalNode() bool {
9487	return (node.level > 0) // Not a leaf, but a internal node
9488}
9489func (node *d14nodeT) isLeaf() bool {
9490	return (node.level == 0) // A leaf, contains data
9491}
9492
9493/// A link list of nodes for reinsertion after a delete operation
9494type d14listNodeT struct {
9495	next *d14listNodeT ///< Next in list
9496	node *d14nodeT     ///< Node
9497}
9498
9499const d14notTaken = -1 // indicates that position
9500
9501/// Variables for finding a split partition
9502type d14partitionVarsT struct {
9503	partition [d14maxNodes + 1]int
9504	total     int
9505	minFill   int
9506	count     [2]int
9507	cover     [2]d14rectT
9508	area      [2]float64
9509
9510	branchBuf      [d14maxNodes + 1]d14branchT
9511	branchCount    int
9512	coverSplit     d14rectT
9513	coverSplitArea float64
9514}
9515
9516func d14New() *d14RTree {
9517	// We only support machine word size simple data type eg. integer index or object pointer.
9518	// Since we are storing as union with non data branch
9519	return &d14RTree{
9520		root: &d14nodeT{},
9521	}
9522}
9523
9524/// Insert entry
9525/// \param a_min Min of bounding rect
9526/// \param a_max Max of bounding rect
9527/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
9528func (tr *d14RTree) Insert(min, max [d14numDims]float64, dataId interface{}) {
9529	var branch d14branchT
9530	branch.data = dataId
9531	for axis := 0; axis < d14numDims; axis++ {
9532		branch.rect.min[axis] = min[axis]
9533		branch.rect.max[axis] = max[axis]
9534	}
9535	d14insertRect(&branch, &tr.root, 0)
9536}
9537
9538/// Remove entry
9539/// \param a_min Min of bounding rect
9540/// \param a_max Max of bounding rect
9541/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
9542func (tr *d14RTree) Remove(min, max [d14numDims]float64, dataId interface{}) {
9543	var rect d14rectT
9544	for axis := 0; axis < d14numDims; axis++ {
9545		rect.min[axis] = min[axis]
9546		rect.max[axis] = max[axis]
9547	}
9548	d14removeRect(&rect, dataId, &tr.root)
9549}
9550
9551/// Find all within d14search rectangle
9552/// \param a_min Min of d14search bounding rect
9553/// \param a_max Max of d14search bounding rect
9554/// \param a_searchResult d14search result array.  Caller should set grow size. Function will reset, not append to array.
9555/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
9556/// \param a_context User context to pass as parameter to a_resultCallback
9557/// \return Returns the number of entries found
9558func (tr *d14RTree) Search(min, max [d14numDims]float64, resultCallback func(data interface{}) bool) int {
9559	var rect d14rectT
9560	for axis := 0; axis < d14numDims; axis++ {
9561		rect.min[axis] = min[axis]
9562		rect.max[axis] = max[axis]
9563	}
9564	foundCount, _ := d14search(tr.root, rect, 0, resultCallback)
9565	return foundCount
9566}
9567
9568/// Count the data elements in this container.  This is slow as no internal counter is maintained.
9569func (tr *d14RTree) Count() int {
9570	var count int
9571	d14countRec(tr.root, &count)
9572	return count
9573}
9574
9575/// Remove all entries from tree
9576func (tr *d14RTree) RemoveAll() {
9577	// Delete all existing nodes
9578	tr.root = &d14nodeT{}
9579}
9580
9581func d14countRec(node *d14nodeT, count *int) {
9582	if node.isInternalNode() { // not a leaf node
9583		for index := 0; index < node.count; index++ {
9584			d14countRec(node.branch[index].child, count)
9585		}
9586	} else { // A leaf node
9587		*count += node.count
9588	}
9589}
9590
9591// Inserts a new data rectangle into the index structure.
9592// Recursively descends tree, propagates splits back up.
9593// Returns 0 if node was not split.  Old node updated.
9594// If node was split, returns 1 and sets the pointer pointed to by
9595// new_node to point to the new node.  Old node updated to become one of two.
9596// The level argument specifies the number of steps up from the leaf
9597// level to insert; e.g. a data rectangle goes in at level = 0.
9598func d14insertRectRec(branch *d14branchT, node *d14nodeT, newNode **d14nodeT, level int) bool {
9599	// recurse until we reach the correct level for the new record. data records
9600	// will always be called with a_level == 0 (leaf)
9601	if node.level > level {
9602		// Still above level for insertion, go down tree recursively
9603		var otherNode *d14nodeT
9604		//var newBranch d14branchT
9605
9606		// find the optimal branch for this record
9607		index := d14pickBranch(&branch.rect, node)
9608
9609		// recursively insert this record into the picked branch
9610		childWasSplit := d14insertRectRec(branch, node.branch[index].child, &otherNode, level)
9611
9612		if !childWasSplit {
9613			// Child was not split. Merge the bounding box of the new record with the
9614			// existing bounding box
9615			node.branch[index].rect = d14combineRect(&branch.rect, &(node.branch[index].rect))
9616			return false
9617		} else {
9618			// Child was split. The old branches are now re-partitioned to two nodes
9619			// so we have to re-calculate the bounding boxes of each node
9620			node.branch[index].rect = d14nodeCover(node.branch[index].child)
9621			var newBranch d14branchT
9622			newBranch.child = otherNode
9623			newBranch.rect = d14nodeCover(otherNode)
9624
9625			// The old node is already a child of a_node. Now add the newly-created
9626			// node to a_node as well. a_node might be split because of that.
9627			return d14addBranch(&newBranch, node, newNode)
9628		}
9629	} else if node.level == level {
9630		// We have reached level for insertion. Add rect, split if necessary
9631		return d14addBranch(branch, node, newNode)
9632	} else {
9633		// Should never occur
9634		return false
9635	}
9636}
9637
9638// Insert a data rectangle into an index structure.
9639// d14insertRect provides for splitting the root;
9640// returns 1 if root was split, 0 if it was not.
9641// The level argument specifies the number of steps up from the leaf
9642// level to insert; e.g. a data rectangle goes in at level = 0.
9643// InsertRect2 does the recursion.
9644//
9645func d14insertRect(branch *d14branchT, root **d14nodeT, level int) bool {
9646	var newNode *d14nodeT
9647
9648	if d14insertRectRec(branch, *root, &newNode, level) { // Root split
9649
9650		// Grow tree taller and new root
9651		newRoot := &d14nodeT{}
9652		newRoot.level = (*root).level + 1
9653
9654		var newBranch d14branchT
9655
9656		// add old root node as a child of the new root
9657		newBranch.rect = d14nodeCover(*root)
9658		newBranch.child = *root
9659		d14addBranch(&newBranch, newRoot, nil)
9660
9661		// add the split node as a child of the new root
9662		newBranch.rect = d14nodeCover(newNode)
9663		newBranch.child = newNode
9664		d14addBranch(&newBranch, newRoot, nil)
9665
9666		// set the new root as the root node
9667		*root = newRoot
9668
9669		return true
9670	}
9671	return false
9672}
9673
9674// Find the smallest rectangle that includes all rectangles in branches of a node.
9675func d14nodeCover(node *d14nodeT) d14rectT {
9676	rect := node.branch[0].rect
9677	for index := 1; index < node.count; index++ {
9678		rect = d14combineRect(&rect, &(node.branch[index].rect))
9679	}
9680	return rect
9681}
9682
9683// Add a branch to a node.  Split the node if necessary.
9684// Returns 0 if node not split.  Old node updated.
9685// Returns 1 if node split, sets *new_node to address of new node.
9686// Old node updated, becomes one of two.
9687func d14addBranch(branch *d14branchT, node *d14nodeT, newNode **d14nodeT) bool {
9688	if node.count < d14maxNodes { // Split won't be necessary
9689		node.branch[node.count] = *branch
9690		node.count++
9691		return false
9692	} else {
9693		d14splitNode(node, branch, newNode)
9694		return true
9695	}
9696}
9697
9698// Disconnect a dependent node.
9699// Caller must return (or stop using iteration index) after this as count has changed
9700func d14disconnectBranch(node *d14nodeT, index int) {
9701	// Remove element by swapping with the last element to prevent gaps in array
9702	node.branch[index] = node.branch[node.count-1]
9703	node.branch[node.count-1].data = nil
9704	node.branch[node.count-1].child = nil
9705	node.count--
9706}
9707
9708// Pick a branch.  Pick the one that will need the smallest increase
9709// in area to accomodate the new rectangle.  This will result in the
9710// least total area for the covering rectangles in the current node.
9711// In case of a tie, pick the one which was smaller before, to get
9712// the best resolution when searching.
9713func d14pickBranch(rect *d14rectT, node *d14nodeT) int {
9714	var firstTime bool = true
9715	var increase float64
9716	var bestIncr float64 = -1
9717	var area float64
9718	var bestArea float64
9719	var best int
9720	var tempRect d14rectT
9721
9722	for index := 0; index < node.count; index++ {
9723		curRect := &node.branch[index].rect
9724		area = d14calcRectVolume(curRect)
9725		tempRect = d14combineRect(rect, curRect)
9726		increase = d14calcRectVolume(&tempRect) - area
9727		if (increase < bestIncr) || firstTime {
9728			best = index
9729			bestArea = area
9730			bestIncr = increase
9731			firstTime = false
9732		} else if (increase == bestIncr) && (area < bestArea) {
9733			best = index
9734			bestArea = area
9735			bestIncr = increase
9736		}
9737	}
9738	return best
9739}
9740
9741// Combine two rectangles into larger one containing both
9742func d14combineRect(rectA, rectB *d14rectT) d14rectT {
9743	var newRect d14rectT
9744
9745	for index := 0; index < d14numDims; index++ {
9746		newRect.min[index] = d14fmin(rectA.min[index], rectB.min[index])
9747		newRect.max[index] = d14fmax(rectA.max[index], rectB.max[index])
9748	}
9749
9750	return newRect
9751}
9752
9753// Split a node.
9754// Divides the nodes branches and the extra one between two nodes.
9755// Old node is one of the new ones, and one really new one is created.
9756// Tries more than one method for choosing a partition, uses best result.
9757func d14splitNode(node *d14nodeT, branch *d14branchT, newNode **d14nodeT) {
9758	// Could just use local here, but member or external is faster since it is reused
9759	var localVars d14partitionVarsT
9760	parVars := &localVars
9761
9762	// Load all the branches into a buffer, initialize old node
9763	d14getBranches(node, branch, parVars)
9764
9765	// Find partition
9766	d14choosePartition(parVars, d14minNodes)
9767
9768	// Create a new node to hold (about) half of the branches
9769	*newNode = &d14nodeT{}
9770	(*newNode).level = node.level
9771
9772	// Put branches from buffer into 2 nodes according to the chosen partition
9773	node.count = 0
9774	d14loadNodes(node, *newNode, parVars)
9775}
9776
9777// Calculate the n-dimensional volume of a rectangle
9778func d14rectVolume(rect *d14rectT) float64 {
9779	var volume float64 = 1
9780	for index := 0; index < d14numDims; index++ {
9781		volume *= rect.max[index] - rect.min[index]
9782	}
9783	return volume
9784}
9785
9786// The exact volume of the bounding sphere for the given d14rectT
9787func d14rectSphericalVolume(rect *d14rectT) float64 {
9788	var sumOfSquares float64 = 0
9789	var radius float64
9790
9791	for index := 0; index < d14numDims; index++ {
9792		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
9793		sumOfSquares += halfExtent * halfExtent
9794	}
9795
9796	radius = math.Sqrt(sumOfSquares)
9797
9798	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
9799	if d14numDims == 5 {
9800		return (radius * radius * radius * radius * radius * d14unitSphereVolume)
9801	} else if d14numDims == 4 {
9802		return (radius * radius * radius * radius * d14unitSphereVolume)
9803	} else if d14numDims == 3 {
9804		return (radius * radius * radius * d14unitSphereVolume)
9805	} else if d14numDims == 2 {
9806		return (radius * radius * d14unitSphereVolume)
9807	} else {
9808		return (math.Pow(radius, d14numDims) * d14unitSphereVolume)
9809	}
9810}
9811
9812// Use one of the methods to calculate retangle volume
9813func d14calcRectVolume(rect *d14rectT) float64 {
9814	if d14useSphericalVolume {
9815		return d14rectSphericalVolume(rect) // Slower but helps certain merge cases
9816	} else { // RTREE_USE_SPHERICAL_VOLUME
9817		return d14rectVolume(rect) // Faster but can cause poor merges
9818	} // RTREE_USE_SPHERICAL_VOLUME
9819}
9820
9821// Load branch buffer with branches from full node plus the extra branch.
9822func d14getBranches(node *d14nodeT, branch *d14branchT, parVars *d14partitionVarsT) {
9823	// Load the branch buffer
9824	for index := 0; index < d14maxNodes; index++ {
9825		parVars.branchBuf[index] = node.branch[index]
9826	}
9827	parVars.branchBuf[d14maxNodes] = *branch
9828	parVars.branchCount = d14maxNodes + 1
9829
9830	// Calculate rect containing all in the set
9831	parVars.coverSplit = parVars.branchBuf[0].rect
9832	for index := 1; index < d14maxNodes+1; index++ {
9833		parVars.coverSplit = d14combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
9834	}
9835	parVars.coverSplitArea = d14calcRectVolume(&parVars.coverSplit)
9836}
9837
9838// Method #0 for choosing a partition:
9839// As the seeds for the two groups, pick the two rects that would waste the
9840// most area if covered by a single rectangle, i.e. evidently the worst pair
9841// to have in the same group.
9842// Of the remaining, one at a time is chosen to be put in one of the two groups.
9843// The one chosen is the one with the greatest difference in area expansion
9844// depending on which group - the rect most strongly attracted to one group
9845// and repelled from the other.
9846// If one group gets too full (more would force other group to violate min
9847// fill requirement) then other group gets the rest.
9848// These last are the ones that can go in either group most easily.
9849func d14choosePartition(parVars *d14partitionVarsT, minFill int) {
9850	var biggestDiff float64
9851	var group, chosen, betterGroup int
9852
9853	d14initParVars(parVars, parVars.branchCount, minFill)
9854	d14pickSeeds(parVars)
9855
9856	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
9857		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
9858		(parVars.count[1] < (parVars.total - parVars.minFill)) {
9859		biggestDiff = -1
9860		for index := 0; index < parVars.total; index++ {
9861			if d14notTaken == parVars.partition[index] {
9862				curRect := &parVars.branchBuf[index].rect
9863				rect0 := d14combineRect(curRect, &parVars.cover[0])
9864				rect1 := d14combineRect(curRect, &parVars.cover[1])
9865				growth0 := d14calcRectVolume(&rect0) - parVars.area[0]
9866				growth1 := d14calcRectVolume(&rect1) - parVars.area[1]
9867				diff := growth1 - growth0
9868				if diff >= 0 {
9869					group = 0
9870				} else {
9871					group = 1
9872					diff = -diff
9873				}
9874
9875				if diff > biggestDiff {
9876					biggestDiff = diff
9877					chosen = index
9878					betterGroup = group
9879				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
9880					chosen = index
9881					betterGroup = group
9882				}
9883			}
9884		}
9885		d14classify(chosen, betterGroup, parVars)
9886	}
9887
9888	// If one group too full, put remaining rects in the other
9889	if (parVars.count[0] + parVars.count[1]) < parVars.total {
9890		if parVars.count[0] >= parVars.total-parVars.minFill {
9891			group = 1
9892		} else {
9893			group = 0
9894		}
9895		for index := 0; index < parVars.total; index++ {
9896			if d14notTaken == parVars.partition[index] {
9897				d14classify(index, group, parVars)
9898			}
9899		}
9900	}
9901}
9902
9903// Copy branches from the buffer into two nodes according to the partition.
9904func d14loadNodes(nodeA, nodeB *d14nodeT, parVars *d14partitionVarsT) {
9905	for index := 0; index < parVars.total; index++ {
9906		targetNodeIndex := parVars.partition[index]
9907		targetNodes := []*d14nodeT{nodeA, nodeB}
9908
9909		// It is assured that d14addBranch here will not cause a node split.
9910		d14addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
9911	}
9912}
9913
9914// Initialize a d14partitionVarsT structure.
9915func d14initParVars(parVars *d14partitionVarsT, maxRects, minFill int) {
9916	parVars.count[0] = 0
9917	parVars.count[1] = 0
9918	parVars.area[0] = 0
9919	parVars.area[1] = 0
9920	parVars.total = maxRects
9921	parVars.minFill = minFill
9922	for index := 0; index < maxRects; index++ {
9923		parVars.partition[index] = d14notTaken
9924	}
9925}
9926
9927func d14pickSeeds(parVars *d14partitionVarsT) {
9928	var seed0, seed1 int
9929	var worst, waste float64
9930	var area [d14maxNodes + 1]float64
9931
9932	for index := 0; index < parVars.total; index++ {
9933		area[index] = d14calcRectVolume(&parVars.branchBuf[index].rect)
9934	}
9935
9936	worst = -parVars.coverSplitArea - 1
9937	for indexA := 0; indexA < parVars.total-1; indexA++ {
9938		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
9939			oneRect := d14combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
9940			waste = d14calcRectVolume(&oneRect) - area[indexA] - area[indexB]
9941			if waste > worst {
9942				worst = waste
9943				seed0 = indexA
9944				seed1 = indexB
9945			}
9946		}
9947	}
9948
9949	d14classify(seed0, 0, parVars)
9950	d14classify(seed1, 1, parVars)
9951}
9952
9953// Put a branch in one of the groups.
9954func d14classify(index, group int, parVars *d14partitionVarsT) {
9955	parVars.partition[index] = group
9956
9957	// Calculate combined rect
9958	if parVars.count[group] == 0 {
9959		parVars.cover[group] = parVars.branchBuf[index].rect
9960	} else {
9961		parVars.cover[group] = d14combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
9962	}
9963
9964	// Calculate volume of combined rect
9965	parVars.area[group] = d14calcRectVolume(&parVars.cover[group])
9966
9967	parVars.count[group]++
9968}
9969
9970// Delete a data rectangle from an index structure.
9971// Pass in a pointer to a d14rectT, the tid of the record, ptr to ptr to root node.
9972// Returns 1 if record not found, 0 if success.
9973// d14removeRect provides for eliminating the root.
9974func d14removeRect(rect *d14rectT, id interface{}, root **d14nodeT) bool {
9975	var reInsertList *d14listNodeT
9976
9977	if !d14removeRectRec(rect, id, *root, &reInsertList) {
9978		// Found and deleted a data item
9979		// Reinsert any branches from eliminated nodes
9980		for reInsertList != nil {
9981			tempNode := reInsertList.node
9982
9983			for index := 0; index < tempNode.count; index++ {
9984				// TODO go over this code. should I use (tempNode->m_level - 1)?
9985				d14insertRect(&tempNode.branch[index], root, tempNode.level)
9986			}
9987			reInsertList = reInsertList.next
9988		}
9989
9990		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
9991		// if with while? In case there is a whole branch of redundant roots...
9992		if (*root).count == 1 && (*root).isInternalNode() {
9993			tempNode := (*root).branch[0].child
9994			*root = tempNode
9995		}
9996		return false
9997	} else {
9998		return true
9999	}
10000}
10001
10002// Delete a rectangle from non-root part of an index structure.
10003// Called by d14removeRect.  Descends tree recursively,
10004// merges branches on the way back up.
10005// Returns 1 if record not found, 0 if success.
10006func d14removeRectRec(rect *d14rectT, id interface{}, node *d14nodeT, listNode **d14listNodeT) bool {
10007	if node.isInternalNode() { // not a leaf node
10008		for index := 0; index < node.count; index++ {
10009			if d14overlap(*rect, node.branch[index].rect) {
10010				if !d14removeRectRec(rect, id, node.branch[index].child, listNode) {
10011					if node.branch[index].child.count >= d14minNodes {
10012						// child removed, just resize parent rect
10013						node.branch[index].rect = d14nodeCover(node.branch[index].child)
10014					} else {
10015						// child removed, not enough entries in node, eliminate node
10016						d14reInsert(node.branch[index].child, listNode)
10017						d14disconnectBranch(node, index) // Must return after this call as count has changed
10018					}
10019					return false
10020				}
10021			}
10022		}
10023		return true
10024	} else { // A leaf node
10025		for index := 0; index < node.count; index++ {
10026			if node.branch[index].data == id {
10027				d14disconnectBranch(node, index) // Must return after this call as count has changed
10028				return false
10029			}
10030		}
10031		return true
10032	}
10033}
10034
10035// Decide whether two rectangles d14overlap.
10036func d14overlap(rectA, rectB d14rectT) bool {
10037	for index := 0; index < d14numDims; index++ {
10038		if rectA.min[index] > rectB.max[index] ||
10039			rectB.min[index] > rectA.max[index] {
10040			return false
10041		}
10042	}
10043	return true
10044}
10045
10046// Add a node to the reinsertion list.  All its branches will later
10047// be reinserted into the index structure.
10048func d14reInsert(node *d14nodeT, listNode **d14listNodeT) {
10049	newListNode := &d14listNodeT{}
10050	newListNode.node = node
10051	newListNode.next = *listNode
10052	*listNode = newListNode
10053}
10054
10055// d14search in an index tree or subtree for all data retangles that d14overlap the argument rectangle.
10056func d14search(node *d14nodeT, rect d14rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
10057	if node.isInternalNode() {
10058		// This is an internal node in the tree
10059		for index := 0; index < node.count; index++ {
10060			if d14overlap(rect, node.branch[index].rect) {
10061				var ok bool
10062				foundCount, ok = d14search(node.branch[index].child, rect, foundCount, resultCallback)
10063				if !ok {
10064					// The callback indicated to stop searching
10065					return foundCount, false
10066				}
10067			}
10068		}
10069	} else {
10070		// This is a leaf node
10071		for index := 0; index < node.count; index++ {
10072			if d14overlap(rect, node.branch[index].rect) {
10073				id := node.branch[index].data
10074				foundCount++
10075				if !resultCallback(id) {
10076					return foundCount, false // Don't continue searching
10077				}
10078
10079			}
10080		}
10081	}
10082	return foundCount, true // Continue searching
10083}
10084
10085func d15fmin(a, b float64) float64 {
10086	if a < b {
10087		return a
10088	}
10089	return b
10090}
10091func d15fmax(a, b float64) float64 {
10092	if a > b {
10093		return a
10094	}
10095	return b
10096}
10097
10098const (
10099	d15numDims            = 15
10100	d15maxNodes           = 8
10101	d15minNodes           = d15maxNodes / 2
10102	d15useSphericalVolume = true // Better split classification, may be slower on some systems
10103)
10104
10105var d15unitSphereVolume = []float64{
10106	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
10107	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
10108	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
10109	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
10110	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
10111	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
10112	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
10113}[d15numDims]
10114
10115type d15RTree struct {
10116	root *d15nodeT ///< Root of tree
10117}
10118
10119/// Minimal bounding rectangle (n-dimensional)
10120type d15rectT struct {
10121	min [d15numDims]float64 ///< Min dimensions of bounding box
10122	max [d15numDims]float64 ///< Max dimensions of bounding box
10123}
10124
10125/// May be data or may be another subtree
10126/// The parents level determines this.
10127/// If the parents level is 0, then this is data
10128type d15branchT struct {
10129	rect  d15rectT    ///< Bounds
10130	child *d15nodeT   ///< Child node
10131	data  interface{} ///< Data Id or Ptr
10132}
10133
10134/// d15nodeT for each branch level
10135type d15nodeT struct {
10136	count  int                     ///< Count
10137	level  int                     ///< Leaf is zero, others positive
10138	branch [d15maxNodes]d15branchT ///< Branch
10139}
10140
10141func (node *d15nodeT) isInternalNode() bool {
10142	return (node.level > 0) // Not a leaf, but a internal node
10143}
10144func (node *d15nodeT) isLeaf() bool {
10145	return (node.level == 0) // A leaf, contains data
10146}
10147
10148/// A link list of nodes for reinsertion after a delete operation
10149type d15listNodeT struct {
10150	next *d15listNodeT ///< Next in list
10151	node *d15nodeT     ///< Node
10152}
10153
10154const d15notTaken = -1 // indicates that position
10155
10156/// Variables for finding a split partition
10157type d15partitionVarsT struct {
10158	partition [d15maxNodes + 1]int
10159	total     int
10160	minFill   int
10161	count     [2]int
10162	cover     [2]d15rectT
10163	area      [2]float64
10164
10165	branchBuf      [d15maxNodes + 1]d15branchT
10166	branchCount    int
10167	coverSplit     d15rectT
10168	coverSplitArea float64
10169}
10170
10171func d15New() *d15RTree {
10172	// We only support machine word size simple data type eg. integer index or object pointer.
10173	// Since we are storing as union with non data branch
10174	return &d15RTree{
10175		root: &d15nodeT{},
10176	}
10177}
10178
10179/// Insert entry
10180/// \param a_min Min of bounding rect
10181/// \param a_max Max of bounding rect
10182/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
10183func (tr *d15RTree) Insert(min, max [d15numDims]float64, dataId interface{}) {
10184	var branch d15branchT
10185	branch.data = dataId
10186	for axis := 0; axis < d15numDims; axis++ {
10187		branch.rect.min[axis] = min[axis]
10188		branch.rect.max[axis] = max[axis]
10189	}
10190	d15insertRect(&branch, &tr.root, 0)
10191}
10192
10193/// Remove entry
10194/// \param a_min Min of bounding rect
10195/// \param a_max Max of bounding rect
10196/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
10197func (tr *d15RTree) Remove(min, max [d15numDims]float64, dataId interface{}) {
10198	var rect d15rectT
10199	for axis := 0; axis < d15numDims; axis++ {
10200		rect.min[axis] = min[axis]
10201		rect.max[axis] = max[axis]
10202	}
10203	d15removeRect(&rect, dataId, &tr.root)
10204}
10205
10206/// Find all within d15search rectangle
10207/// \param a_min Min of d15search bounding rect
10208/// \param a_max Max of d15search bounding rect
10209/// \param a_searchResult d15search result array.  Caller should set grow size. Function will reset, not append to array.
10210/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
10211/// \param a_context User context to pass as parameter to a_resultCallback
10212/// \return Returns the number of entries found
10213func (tr *d15RTree) Search(min, max [d15numDims]float64, resultCallback func(data interface{}) bool) int {
10214	var rect d15rectT
10215	for axis := 0; axis < d15numDims; axis++ {
10216		rect.min[axis] = min[axis]
10217		rect.max[axis] = max[axis]
10218	}
10219	foundCount, _ := d15search(tr.root, rect, 0, resultCallback)
10220	return foundCount
10221}
10222
10223/// Count the data elements in this container.  This is slow as no internal counter is maintained.
10224func (tr *d15RTree) Count() int {
10225	var count int
10226	d15countRec(tr.root, &count)
10227	return count
10228}
10229
10230/// Remove all entries from tree
10231func (tr *d15RTree) RemoveAll() {
10232	// Delete all existing nodes
10233	tr.root = &d15nodeT{}
10234}
10235
10236func d15countRec(node *d15nodeT, count *int) {
10237	if node.isInternalNode() { // not a leaf node
10238		for index := 0; index < node.count; index++ {
10239			d15countRec(node.branch[index].child, count)
10240		}
10241	} else { // A leaf node
10242		*count += node.count
10243	}
10244}
10245
10246// Inserts a new data rectangle into the index structure.
10247// Recursively descends tree, propagates splits back up.
10248// Returns 0 if node was not split.  Old node updated.
10249// If node was split, returns 1 and sets the pointer pointed to by
10250// new_node to point to the new node.  Old node updated to become one of two.
10251// The level argument specifies the number of steps up from the leaf
10252// level to insert; e.g. a data rectangle goes in at level = 0.
10253func d15insertRectRec(branch *d15branchT, node *d15nodeT, newNode **d15nodeT, level int) bool {
10254	// recurse until we reach the correct level for the new record. data records
10255	// will always be called with a_level == 0 (leaf)
10256	if node.level > level {
10257		// Still above level for insertion, go down tree recursively
10258		var otherNode *d15nodeT
10259		//var newBranch d15branchT
10260
10261		// find the optimal branch for this record
10262		index := d15pickBranch(&branch.rect, node)
10263
10264		// recursively insert this record into the picked branch
10265		childWasSplit := d15insertRectRec(branch, node.branch[index].child, &otherNode, level)
10266
10267		if !childWasSplit {
10268			// Child was not split. Merge the bounding box of the new record with the
10269			// existing bounding box
10270			node.branch[index].rect = d15combineRect(&branch.rect, &(node.branch[index].rect))
10271			return false
10272		} else {
10273			// Child was split. The old branches are now re-partitioned to two nodes
10274			// so we have to re-calculate the bounding boxes of each node
10275			node.branch[index].rect = d15nodeCover(node.branch[index].child)
10276			var newBranch d15branchT
10277			newBranch.child = otherNode
10278			newBranch.rect = d15nodeCover(otherNode)
10279
10280			// The old node is already a child of a_node. Now add the newly-created
10281			// node to a_node as well. a_node might be split because of that.
10282			return d15addBranch(&newBranch, node, newNode)
10283		}
10284	} else if node.level == level {
10285		// We have reached level for insertion. Add rect, split if necessary
10286		return d15addBranch(branch, node, newNode)
10287	} else {
10288		// Should never occur
10289		return false
10290	}
10291}
10292
10293// Insert a data rectangle into an index structure.
10294// d15insertRect provides for splitting the root;
10295// returns 1 if root was split, 0 if it was not.
10296// The level argument specifies the number of steps up from the leaf
10297// level to insert; e.g. a data rectangle goes in at level = 0.
10298// InsertRect2 does the recursion.
10299//
10300func d15insertRect(branch *d15branchT, root **d15nodeT, level int) bool {
10301	var newNode *d15nodeT
10302
10303	if d15insertRectRec(branch, *root, &newNode, level) { // Root split
10304
10305		// Grow tree taller and new root
10306		newRoot := &d15nodeT{}
10307		newRoot.level = (*root).level + 1
10308
10309		var newBranch d15branchT
10310
10311		// add old root node as a child of the new root
10312		newBranch.rect = d15nodeCover(*root)
10313		newBranch.child = *root
10314		d15addBranch(&newBranch, newRoot, nil)
10315
10316		// add the split node as a child of the new root
10317		newBranch.rect = d15nodeCover(newNode)
10318		newBranch.child = newNode
10319		d15addBranch(&newBranch, newRoot, nil)
10320
10321		// set the new root as the root node
10322		*root = newRoot
10323
10324		return true
10325	}
10326	return false
10327}
10328
10329// Find the smallest rectangle that includes all rectangles in branches of a node.
10330func d15nodeCover(node *d15nodeT) d15rectT {
10331	rect := node.branch[0].rect
10332	for index := 1; index < node.count; index++ {
10333		rect = d15combineRect(&rect, &(node.branch[index].rect))
10334	}
10335	return rect
10336}
10337
10338// Add a branch to a node.  Split the node if necessary.
10339// Returns 0 if node not split.  Old node updated.
10340// Returns 1 if node split, sets *new_node to address of new node.
10341// Old node updated, becomes one of two.
10342func d15addBranch(branch *d15branchT, node *d15nodeT, newNode **d15nodeT) bool {
10343	if node.count < d15maxNodes { // Split won't be necessary
10344		node.branch[node.count] = *branch
10345		node.count++
10346		return false
10347	} else {
10348		d15splitNode(node, branch, newNode)
10349		return true
10350	}
10351}
10352
10353// Disconnect a dependent node.
10354// Caller must return (or stop using iteration index) after this as count has changed
10355func d15disconnectBranch(node *d15nodeT, index int) {
10356	// Remove element by swapping with the last element to prevent gaps in array
10357	node.branch[index] = node.branch[node.count-1]
10358	node.branch[node.count-1].data = nil
10359	node.branch[node.count-1].child = nil
10360	node.count--
10361}
10362
10363// Pick a branch.  Pick the one that will need the smallest increase
10364// in area to accomodate the new rectangle.  This will result in the
10365// least total area for the covering rectangles in the current node.
10366// In case of a tie, pick the one which was smaller before, to get
10367// the best resolution when searching.
10368func d15pickBranch(rect *d15rectT, node *d15nodeT) int {
10369	var firstTime bool = true
10370	var increase float64
10371	var bestIncr float64 = -1
10372	var area float64
10373	var bestArea float64
10374	var best int
10375	var tempRect d15rectT
10376
10377	for index := 0; index < node.count; index++ {
10378		curRect := &node.branch[index].rect
10379		area = d15calcRectVolume(curRect)
10380		tempRect = d15combineRect(rect, curRect)
10381		increase = d15calcRectVolume(&tempRect) - area
10382		if (increase < bestIncr) || firstTime {
10383			best = index
10384			bestArea = area
10385			bestIncr = increase
10386			firstTime = false
10387		} else if (increase == bestIncr) && (area < bestArea) {
10388			best = index
10389			bestArea = area
10390			bestIncr = increase
10391		}
10392	}
10393	return best
10394}
10395
10396// Combine two rectangles into larger one containing both
10397func d15combineRect(rectA, rectB *d15rectT) d15rectT {
10398	var newRect d15rectT
10399
10400	for index := 0; index < d15numDims; index++ {
10401		newRect.min[index] = d15fmin(rectA.min[index], rectB.min[index])
10402		newRect.max[index] = d15fmax(rectA.max[index], rectB.max[index])
10403	}
10404
10405	return newRect
10406}
10407
10408// Split a node.
10409// Divides the nodes branches and the extra one between two nodes.
10410// Old node is one of the new ones, and one really new one is created.
10411// Tries more than one method for choosing a partition, uses best result.
10412func d15splitNode(node *d15nodeT, branch *d15branchT, newNode **d15nodeT) {
10413	// Could just use local here, but member or external is faster since it is reused
10414	var localVars d15partitionVarsT
10415	parVars := &localVars
10416
10417	// Load all the branches into a buffer, initialize old node
10418	d15getBranches(node, branch, parVars)
10419
10420	// Find partition
10421	d15choosePartition(parVars, d15minNodes)
10422
10423	// Create a new node to hold (about) half of the branches
10424	*newNode = &d15nodeT{}
10425	(*newNode).level = node.level
10426
10427	// Put branches from buffer into 2 nodes according to the chosen partition
10428	node.count = 0
10429	d15loadNodes(node, *newNode, parVars)
10430}
10431
10432// Calculate the n-dimensional volume of a rectangle
10433func d15rectVolume(rect *d15rectT) float64 {
10434	var volume float64 = 1
10435	for index := 0; index < d15numDims; index++ {
10436		volume *= rect.max[index] - rect.min[index]
10437	}
10438	return volume
10439}
10440
10441// The exact volume of the bounding sphere for the given d15rectT
10442func d15rectSphericalVolume(rect *d15rectT) float64 {
10443	var sumOfSquares float64 = 0
10444	var radius float64
10445
10446	for index := 0; index < d15numDims; index++ {
10447		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
10448		sumOfSquares += halfExtent * halfExtent
10449	}
10450
10451	radius = math.Sqrt(sumOfSquares)
10452
10453	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
10454	if d15numDims == 5 {
10455		return (radius * radius * radius * radius * radius * d15unitSphereVolume)
10456	} else if d15numDims == 4 {
10457		return (radius * radius * radius * radius * d15unitSphereVolume)
10458	} else if d15numDims == 3 {
10459		return (radius * radius * radius * d15unitSphereVolume)
10460	} else if d15numDims == 2 {
10461		return (radius * radius * d15unitSphereVolume)
10462	} else {
10463		return (math.Pow(radius, d15numDims) * d15unitSphereVolume)
10464	}
10465}
10466
10467// Use one of the methods to calculate retangle volume
10468func d15calcRectVolume(rect *d15rectT) float64 {
10469	if d15useSphericalVolume {
10470		return d15rectSphericalVolume(rect) // Slower but helps certain merge cases
10471	} else { // RTREE_USE_SPHERICAL_VOLUME
10472		return d15rectVolume(rect) // Faster but can cause poor merges
10473	} // RTREE_USE_SPHERICAL_VOLUME
10474}
10475
10476// Load branch buffer with branches from full node plus the extra branch.
10477func d15getBranches(node *d15nodeT, branch *d15branchT, parVars *d15partitionVarsT) {
10478	// Load the branch buffer
10479	for index := 0; index < d15maxNodes; index++ {
10480		parVars.branchBuf[index] = node.branch[index]
10481	}
10482	parVars.branchBuf[d15maxNodes] = *branch
10483	parVars.branchCount = d15maxNodes + 1
10484
10485	// Calculate rect containing all in the set
10486	parVars.coverSplit = parVars.branchBuf[0].rect
10487	for index := 1; index < d15maxNodes+1; index++ {
10488		parVars.coverSplit = d15combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
10489	}
10490	parVars.coverSplitArea = d15calcRectVolume(&parVars.coverSplit)
10491}
10492
10493// Method #0 for choosing a partition:
10494// As the seeds for the two groups, pick the two rects that would waste the
10495// most area if covered by a single rectangle, i.e. evidently the worst pair
10496// to have in the same group.
10497// Of the remaining, one at a time is chosen to be put in one of the two groups.
10498// The one chosen is the one with the greatest difference in area expansion
10499// depending on which group - the rect most strongly attracted to one group
10500// and repelled from the other.
10501// If one group gets too full (more would force other group to violate min
10502// fill requirement) then other group gets the rest.
10503// These last are the ones that can go in either group most easily.
10504func d15choosePartition(parVars *d15partitionVarsT, minFill int) {
10505	var biggestDiff float64
10506	var group, chosen, betterGroup int
10507
10508	d15initParVars(parVars, parVars.branchCount, minFill)
10509	d15pickSeeds(parVars)
10510
10511	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
10512		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
10513		(parVars.count[1] < (parVars.total - parVars.minFill)) {
10514		biggestDiff = -1
10515		for index := 0; index < parVars.total; index++ {
10516			if d15notTaken == parVars.partition[index] {
10517				curRect := &parVars.branchBuf[index].rect
10518				rect0 := d15combineRect(curRect, &parVars.cover[0])
10519				rect1 := d15combineRect(curRect, &parVars.cover[1])
10520				growth0 := d15calcRectVolume(&rect0) - parVars.area[0]
10521				growth1 := d15calcRectVolume(&rect1) - parVars.area[1]
10522				diff := growth1 - growth0
10523				if diff >= 0 {
10524					group = 0
10525				} else {
10526					group = 1
10527					diff = -diff
10528				}
10529
10530				if diff > biggestDiff {
10531					biggestDiff = diff
10532					chosen = index
10533					betterGroup = group
10534				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
10535					chosen = index
10536					betterGroup = group
10537				}
10538			}
10539		}
10540		d15classify(chosen, betterGroup, parVars)
10541	}
10542
10543	// If one group too full, put remaining rects in the other
10544	if (parVars.count[0] + parVars.count[1]) < parVars.total {
10545		if parVars.count[0] >= parVars.total-parVars.minFill {
10546			group = 1
10547		} else {
10548			group = 0
10549		}
10550		for index := 0; index < parVars.total; index++ {
10551			if d15notTaken == parVars.partition[index] {
10552				d15classify(index, group, parVars)
10553			}
10554		}
10555	}
10556}
10557
10558// Copy branches from the buffer into two nodes according to the partition.
10559func d15loadNodes(nodeA, nodeB *d15nodeT, parVars *d15partitionVarsT) {
10560	for index := 0; index < parVars.total; index++ {
10561		targetNodeIndex := parVars.partition[index]
10562		targetNodes := []*d15nodeT{nodeA, nodeB}
10563
10564		// It is assured that d15addBranch here will not cause a node split.
10565		d15addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
10566	}
10567}
10568
10569// Initialize a d15partitionVarsT structure.
10570func d15initParVars(parVars *d15partitionVarsT, maxRects, minFill int) {
10571	parVars.count[0] = 0
10572	parVars.count[1] = 0
10573	parVars.area[0] = 0
10574	parVars.area[1] = 0
10575	parVars.total = maxRects
10576	parVars.minFill = minFill
10577	for index := 0; index < maxRects; index++ {
10578		parVars.partition[index] = d15notTaken
10579	}
10580}
10581
10582func d15pickSeeds(parVars *d15partitionVarsT) {
10583	var seed0, seed1 int
10584	var worst, waste float64
10585	var area [d15maxNodes + 1]float64
10586
10587	for index := 0; index < parVars.total; index++ {
10588		area[index] = d15calcRectVolume(&parVars.branchBuf[index].rect)
10589	}
10590
10591	worst = -parVars.coverSplitArea - 1
10592	for indexA := 0; indexA < parVars.total-1; indexA++ {
10593		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
10594			oneRect := d15combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
10595			waste = d15calcRectVolume(&oneRect) - area[indexA] - area[indexB]
10596			if waste > worst {
10597				worst = waste
10598				seed0 = indexA
10599				seed1 = indexB
10600			}
10601		}
10602	}
10603
10604	d15classify(seed0, 0, parVars)
10605	d15classify(seed1, 1, parVars)
10606}
10607
10608// Put a branch in one of the groups.
10609func d15classify(index, group int, parVars *d15partitionVarsT) {
10610	parVars.partition[index] = group
10611
10612	// Calculate combined rect
10613	if parVars.count[group] == 0 {
10614		parVars.cover[group] = parVars.branchBuf[index].rect
10615	} else {
10616		parVars.cover[group] = d15combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
10617	}
10618
10619	// Calculate volume of combined rect
10620	parVars.area[group] = d15calcRectVolume(&parVars.cover[group])
10621
10622	parVars.count[group]++
10623}
10624
10625// Delete a data rectangle from an index structure.
10626// Pass in a pointer to a d15rectT, the tid of the record, ptr to ptr to root node.
10627// Returns 1 if record not found, 0 if success.
10628// d15removeRect provides for eliminating the root.
10629func d15removeRect(rect *d15rectT, id interface{}, root **d15nodeT) bool {
10630	var reInsertList *d15listNodeT
10631
10632	if !d15removeRectRec(rect, id, *root, &reInsertList) {
10633		// Found and deleted a data item
10634		// Reinsert any branches from eliminated nodes
10635		for reInsertList != nil {
10636			tempNode := reInsertList.node
10637
10638			for index := 0; index < tempNode.count; index++ {
10639				// TODO go over this code. should I use (tempNode->m_level - 1)?
10640				d15insertRect(&tempNode.branch[index], root, tempNode.level)
10641			}
10642			reInsertList = reInsertList.next
10643		}
10644
10645		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
10646		// if with while? In case there is a whole branch of redundant roots...
10647		if (*root).count == 1 && (*root).isInternalNode() {
10648			tempNode := (*root).branch[0].child
10649			*root = tempNode
10650		}
10651		return false
10652	} else {
10653		return true
10654	}
10655}
10656
10657// Delete a rectangle from non-root part of an index structure.
10658// Called by d15removeRect.  Descends tree recursively,
10659// merges branches on the way back up.
10660// Returns 1 if record not found, 0 if success.
10661func d15removeRectRec(rect *d15rectT, id interface{}, node *d15nodeT, listNode **d15listNodeT) bool {
10662	if node.isInternalNode() { // not a leaf node
10663		for index := 0; index < node.count; index++ {
10664			if d15overlap(*rect, node.branch[index].rect) {
10665				if !d15removeRectRec(rect, id, node.branch[index].child, listNode) {
10666					if node.branch[index].child.count >= d15minNodes {
10667						// child removed, just resize parent rect
10668						node.branch[index].rect = d15nodeCover(node.branch[index].child)
10669					} else {
10670						// child removed, not enough entries in node, eliminate node
10671						d15reInsert(node.branch[index].child, listNode)
10672						d15disconnectBranch(node, index) // Must return after this call as count has changed
10673					}
10674					return false
10675				}
10676			}
10677		}
10678		return true
10679	} else { // A leaf node
10680		for index := 0; index < node.count; index++ {
10681			if node.branch[index].data == id {
10682				d15disconnectBranch(node, index) // Must return after this call as count has changed
10683				return false
10684			}
10685		}
10686		return true
10687	}
10688}
10689
10690// Decide whether two rectangles d15overlap.
10691func d15overlap(rectA, rectB d15rectT) bool {
10692	for index := 0; index < d15numDims; index++ {
10693		if rectA.min[index] > rectB.max[index] ||
10694			rectB.min[index] > rectA.max[index] {
10695			return false
10696		}
10697	}
10698	return true
10699}
10700
10701// Add a node to the reinsertion list.  All its branches will later
10702// be reinserted into the index structure.
10703func d15reInsert(node *d15nodeT, listNode **d15listNodeT) {
10704	newListNode := &d15listNodeT{}
10705	newListNode.node = node
10706	newListNode.next = *listNode
10707	*listNode = newListNode
10708}
10709
10710// d15search in an index tree or subtree for all data retangles that d15overlap the argument rectangle.
10711func d15search(node *d15nodeT, rect d15rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
10712	if node.isInternalNode() {
10713		// This is an internal node in the tree
10714		for index := 0; index < node.count; index++ {
10715			if d15overlap(rect, node.branch[index].rect) {
10716				var ok bool
10717				foundCount, ok = d15search(node.branch[index].child, rect, foundCount, resultCallback)
10718				if !ok {
10719					// The callback indicated to stop searching
10720					return foundCount, false
10721				}
10722			}
10723		}
10724	} else {
10725		// This is a leaf node
10726		for index := 0; index < node.count; index++ {
10727			if d15overlap(rect, node.branch[index].rect) {
10728				id := node.branch[index].data
10729				foundCount++
10730				if !resultCallback(id) {
10731					return foundCount, false // Don't continue searching
10732				}
10733
10734			}
10735		}
10736	}
10737	return foundCount, true // Continue searching
10738}
10739
10740func d16fmin(a, b float64) float64 {
10741	if a < b {
10742		return a
10743	}
10744	return b
10745}
10746func d16fmax(a, b float64) float64 {
10747	if a > b {
10748		return a
10749	}
10750	return b
10751}
10752
10753const (
10754	d16numDims            = 16
10755	d16maxNodes           = 8
10756	d16minNodes           = d16maxNodes / 2
10757	d16useSphericalVolume = true // Better split classification, may be slower on some systems
10758)
10759
10760var d16unitSphereVolume = []float64{
10761	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
10762	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
10763	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
10764	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
10765	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
10766	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
10767	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
10768}[d16numDims]
10769
10770type d16RTree struct {
10771	root *d16nodeT ///< Root of tree
10772}
10773
10774/// Minimal bounding rectangle (n-dimensional)
10775type d16rectT struct {
10776	min [d16numDims]float64 ///< Min dimensions of bounding box
10777	max [d16numDims]float64 ///< Max dimensions of bounding box
10778}
10779
10780/// May be data or may be another subtree
10781/// The parents level determines this.
10782/// If the parents level is 0, then this is data
10783type d16branchT struct {
10784	rect  d16rectT    ///< Bounds
10785	child *d16nodeT   ///< Child node
10786	data  interface{} ///< Data Id or Ptr
10787}
10788
10789/// d16nodeT for each branch level
10790type d16nodeT struct {
10791	count  int                     ///< Count
10792	level  int                     ///< Leaf is zero, others positive
10793	branch [d16maxNodes]d16branchT ///< Branch
10794}
10795
10796func (node *d16nodeT) isInternalNode() bool {
10797	return (node.level > 0) // Not a leaf, but a internal node
10798}
10799func (node *d16nodeT) isLeaf() bool {
10800	return (node.level == 0) // A leaf, contains data
10801}
10802
10803/// A link list of nodes for reinsertion after a delete operation
10804type d16listNodeT struct {
10805	next *d16listNodeT ///< Next in list
10806	node *d16nodeT     ///< Node
10807}
10808
10809const d16notTaken = -1 // indicates that position
10810
10811/// Variables for finding a split partition
10812type d16partitionVarsT struct {
10813	partition [d16maxNodes + 1]int
10814	total     int
10815	minFill   int
10816	count     [2]int
10817	cover     [2]d16rectT
10818	area      [2]float64
10819
10820	branchBuf      [d16maxNodes + 1]d16branchT
10821	branchCount    int
10822	coverSplit     d16rectT
10823	coverSplitArea float64
10824}
10825
10826func d16New() *d16RTree {
10827	// We only support machine word size simple data type eg. integer index or object pointer.
10828	// Since we are storing as union with non data branch
10829	return &d16RTree{
10830		root: &d16nodeT{},
10831	}
10832}
10833
10834/// Insert entry
10835/// \param a_min Min of bounding rect
10836/// \param a_max Max of bounding rect
10837/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
10838func (tr *d16RTree) Insert(min, max [d16numDims]float64, dataId interface{}) {
10839	var branch d16branchT
10840	branch.data = dataId
10841	for axis := 0; axis < d16numDims; axis++ {
10842		branch.rect.min[axis] = min[axis]
10843		branch.rect.max[axis] = max[axis]
10844	}
10845	d16insertRect(&branch, &tr.root, 0)
10846}
10847
10848/// Remove entry
10849/// \param a_min Min of bounding rect
10850/// \param a_max Max of bounding rect
10851/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
10852func (tr *d16RTree) Remove(min, max [d16numDims]float64, dataId interface{}) {
10853	var rect d16rectT
10854	for axis := 0; axis < d16numDims; axis++ {
10855		rect.min[axis] = min[axis]
10856		rect.max[axis] = max[axis]
10857	}
10858	d16removeRect(&rect, dataId, &tr.root)
10859}
10860
10861/// Find all within d16search rectangle
10862/// \param a_min Min of d16search bounding rect
10863/// \param a_max Max of d16search bounding rect
10864/// \param a_searchResult d16search result array.  Caller should set grow size. Function will reset, not append to array.
10865/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
10866/// \param a_context User context to pass as parameter to a_resultCallback
10867/// \return Returns the number of entries found
10868func (tr *d16RTree) Search(min, max [d16numDims]float64, resultCallback func(data interface{}) bool) int {
10869	var rect d16rectT
10870	for axis := 0; axis < d16numDims; axis++ {
10871		rect.min[axis] = min[axis]
10872		rect.max[axis] = max[axis]
10873	}
10874	foundCount, _ := d16search(tr.root, rect, 0, resultCallback)
10875	return foundCount
10876}
10877
10878/// Count the data elements in this container.  This is slow as no internal counter is maintained.
10879func (tr *d16RTree) Count() int {
10880	var count int
10881	d16countRec(tr.root, &count)
10882	return count
10883}
10884
10885/// Remove all entries from tree
10886func (tr *d16RTree) RemoveAll() {
10887	// Delete all existing nodes
10888	tr.root = &d16nodeT{}
10889}
10890
10891func d16countRec(node *d16nodeT, count *int) {
10892	if node.isInternalNode() { // not a leaf node
10893		for index := 0; index < node.count; index++ {
10894			d16countRec(node.branch[index].child, count)
10895		}
10896	} else { // A leaf node
10897		*count += node.count
10898	}
10899}
10900
10901// Inserts a new data rectangle into the index structure.
10902// Recursively descends tree, propagates splits back up.
10903// Returns 0 if node was not split.  Old node updated.
10904// If node was split, returns 1 and sets the pointer pointed to by
10905// new_node to point to the new node.  Old node updated to become one of two.
10906// The level argument specifies the number of steps up from the leaf
10907// level to insert; e.g. a data rectangle goes in at level = 0.
10908func d16insertRectRec(branch *d16branchT, node *d16nodeT, newNode **d16nodeT, level int) bool {
10909	// recurse until we reach the correct level for the new record. data records
10910	// will always be called with a_level == 0 (leaf)
10911	if node.level > level {
10912		// Still above level for insertion, go down tree recursively
10913		var otherNode *d16nodeT
10914		//var newBranch d16branchT
10915
10916		// find the optimal branch for this record
10917		index := d16pickBranch(&branch.rect, node)
10918
10919		// recursively insert this record into the picked branch
10920		childWasSplit := d16insertRectRec(branch, node.branch[index].child, &otherNode, level)
10921
10922		if !childWasSplit {
10923			// Child was not split. Merge the bounding box of the new record with the
10924			// existing bounding box
10925			node.branch[index].rect = d16combineRect(&branch.rect, &(node.branch[index].rect))
10926			return false
10927		} else {
10928			// Child was split. The old branches are now re-partitioned to two nodes
10929			// so we have to re-calculate the bounding boxes of each node
10930			node.branch[index].rect = d16nodeCover(node.branch[index].child)
10931			var newBranch d16branchT
10932			newBranch.child = otherNode
10933			newBranch.rect = d16nodeCover(otherNode)
10934
10935			// The old node is already a child of a_node. Now add the newly-created
10936			// node to a_node as well. a_node might be split because of that.
10937			return d16addBranch(&newBranch, node, newNode)
10938		}
10939	} else if node.level == level {
10940		// We have reached level for insertion. Add rect, split if necessary
10941		return d16addBranch(branch, node, newNode)
10942	} else {
10943		// Should never occur
10944		return false
10945	}
10946}
10947
10948// Insert a data rectangle into an index structure.
10949// d16insertRect provides for splitting the root;
10950// returns 1 if root was split, 0 if it was not.
10951// The level argument specifies the number of steps up from the leaf
10952// level to insert; e.g. a data rectangle goes in at level = 0.
10953// InsertRect2 does the recursion.
10954//
10955func d16insertRect(branch *d16branchT, root **d16nodeT, level int) bool {
10956	var newNode *d16nodeT
10957
10958	if d16insertRectRec(branch, *root, &newNode, level) { // Root split
10959
10960		// Grow tree taller and new root
10961		newRoot := &d16nodeT{}
10962		newRoot.level = (*root).level + 1
10963
10964		var newBranch d16branchT
10965
10966		// add old root node as a child of the new root
10967		newBranch.rect = d16nodeCover(*root)
10968		newBranch.child = *root
10969		d16addBranch(&newBranch, newRoot, nil)
10970
10971		// add the split node as a child of the new root
10972		newBranch.rect = d16nodeCover(newNode)
10973		newBranch.child = newNode
10974		d16addBranch(&newBranch, newRoot, nil)
10975
10976		// set the new root as the root node
10977		*root = newRoot
10978
10979		return true
10980	}
10981	return false
10982}
10983
10984// Find the smallest rectangle that includes all rectangles in branches of a node.
10985func d16nodeCover(node *d16nodeT) d16rectT {
10986	rect := node.branch[0].rect
10987	for index := 1; index < node.count; index++ {
10988		rect = d16combineRect(&rect, &(node.branch[index].rect))
10989	}
10990	return rect
10991}
10992
10993// Add a branch to a node.  Split the node if necessary.
10994// Returns 0 if node not split.  Old node updated.
10995// Returns 1 if node split, sets *new_node to address of new node.
10996// Old node updated, becomes one of two.
10997func d16addBranch(branch *d16branchT, node *d16nodeT, newNode **d16nodeT) bool {
10998	if node.count < d16maxNodes { // Split won't be necessary
10999		node.branch[node.count] = *branch
11000		node.count++
11001		return false
11002	} else {
11003		d16splitNode(node, branch, newNode)
11004		return true
11005	}
11006}
11007
11008// Disconnect a dependent node.
11009// Caller must return (or stop using iteration index) after this as count has changed
11010func d16disconnectBranch(node *d16nodeT, index int) {
11011	// Remove element by swapping with the last element to prevent gaps in array
11012	node.branch[index] = node.branch[node.count-1]
11013	node.branch[node.count-1].data = nil
11014	node.branch[node.count-1].child = nil
11015	node.count--
11016}
11017
11018// Pick a branch.  Pick the one that will need the smallest increase
11019// in area to accomodate the new rectangle.  This will result in the
11020// least total area for the covering rectangles in the current node.
11021// In case of a tie, pick the one which was smaller before, to get
11022// the best resolution when searching.
11023func d16pickBranch(rect *d16rectT, node *d16nodeT) int {
11024	var firstTime bool = true
11025	var increase float64
11026	var bestIncr float64 = -1
11027	var area float64
11028	var bestArea float64
11029	var best int
11030	var tempRect d16rectT
11031
11032	for index := 0; index < node.count; index++ {
11033		curRect := &node.branch[index].rect
11034		area = d16calcRectVolume(curRect)
11035		tempRect = d16combineRect(rect, curRect)
11036		increase = d16calcRectVolume(&tempRect) - area
11037		if (increase < bestIncr) || firstTime {
11038			best = index
11039			bestArea = area
11040			bestIncr = increase
11041			firstTime = false
11042		} else if (increase == bestIncr) && (area < bestArea) {
11043			best = index
11044			bestArea = area
11045			bestIncr = increase
11046		}
11047	}
11048	return best
11049}
11050
11051// Combine two rectangles into larger one containing both
11052func d16combineRect(rectA, rectB *d16rectT) d16rectT {
11053	var newRect d16rectT
11054
11055	for index := 0; index < d16numDims; index++ {
11056		newRect.min[index] = d16fmin(rectA.min[index], rectB.min[index])
11057		newRect.max[index] = d16fmax(rectA.max[index], rectB.max[index])
11058	}
11059
11060	return newRect
11061}
11062
11063// Split a node.
11064// Divides the nodes branches and the extra one between two nodes.
11065// Old node is one of the new ones, and one really new one is created.
11066// Tries more than one method for choosing a partition, uses best result.
11067func d16splitNode(node *d16nodeT, branch *d16branchT, newNode **d16nodeT) {
11068	// Could just use local here, but member or external is faster since it is reused
11069	var localVars d16partitionVarsT
11070	parVars := &localVars
11071
11072	// Load all the branches into a buffer, initialize old node
11073	d16getBranches(node, branch, parVars)
11074
11075	// Find partition
11076	d16choosePartition(parVars, d16minNodes)
11077
11078	// Create a new node to hold (about) half of the branches
11079	*newNode = &d16nodeT{}
11080	(*newNode).level = node.level
11081
11082	// Put branches from buffer into 2 nodes according to the chosen partition
11083	node.count = 0
11084	d16loadNodes(node, *newNode, parVars)
11085}
11086
11087// Calculate the n-dimensional volume of a rectangle
11088func d16rectVolume(rect *d16rectT) float64 {
11089	var volume float64 = 1
11090	for index := 0; index < d16numDims; index++ {
11091		volume *= rect.max[index] - rect.min[index]
11092	}
11093	return volume
11094}
11095
11096// The exact volume of the bounding sphere for the given d16rectT
11097func d16rectSphericalVolume(rect *d16rectT) float64 {
11098	var sumOfSquares float64 = 0
11099	var radius float64
11100
11101	for index := 0; index < d16numDims; index++ {
11102		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
11103		sumOfSquares += halfExtent * halfExtent
11104	}
11105
11106	radius = math.Sqrt(sumOfSquares)
11107
11108	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
11109	if d16numDims == 5 {
11110		return (radius * radius * radius * radius * radius * d16unitSphereVolume)
11111	} else if d16numDims == 4 {
11112		return (radius * radius * radius * radius * d16unitSphereVolume)
11113	} else if d16numDims == 3 {
11114		return (radius * radius * radius * d16unitSphereVolume)
11115	} else if d16numDims == 2 {
11116		return (radius * radius * d16unitSphereVolume)
11117	} else {
11118		return (math.Pow(radius, d16numDims) * d16unitSphereVolume)
11119	}
11120}
11121
11122// Use one of the methods to calculate retangle volume
11123func d16calcRectVolume(rect *d16rectT) float64 {
11124	if d16useSphericalVolume {
11125		return d16rectSphericalVolume(rect) // Slower but helps certain merge cases
11126	} else { // RTREE_USE_SPHERICAL_VOLUME
11127		return d16rectVolume(rect) // Faster but can cause poor merges
11128	} // RTREE_USE_SPHERICAL_VOLUME
11129}
11130
11131// Load branch buffer with branches from full node plus the extra branch.
11132func d16getBranches(node *d16nodeT, branch *d16branchT, parVars *d16partitionVarsT) {
11133	// Load the branch buffer
11134	for index := 0; index < d16maxNodes; index++ {
11135		parVars.branchBuf[index] = node.branch[index]
11136	}
11137	parVars.branchBuf[d16maxNodes] = *branch
11138	parVars.branchCount = d16maxNodes + 1
11139
11140	// Calculate rect containing all in the set
11141	parVars.coverSplit = parVars.branchBuf[0].rect
11142	for index := 1; index < d16maxNodes+1; index++ {
11143		parVars.coverSplit = d16combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
11144	}
11145	parVars.coverSplitArea = d16calcRectVolume(&parVars.coverSplit)
11146}
11147
11148// Method #0 for choosing a partition:
11149// As the seeds for the two groups, pick the two rects that would waste the
11150// most area if covered by a single rectangle, i.e. evidently the worst pair
11151// to have in the same group.
11152// Of the remaining, one at a time is chosen to be put in one of the two groups.
11153// The one chosen is the one with the greatest difference in area expansion
11154// depending on which group - the rect most strongly attracted to one group
11155// and repelled from the other.
11156// If one group gets too full (more would force other group to violate min
11157// fill requirement) then other group gets the rest.
11158// These last are the ones that can go in either group most easily.
11159func d16choosePartition(parVars *d16partitionVarsT, minFill int) {
11160	var biggestDiff float64
11161	var group, chosen, betterGroup int
11162
11163	d16initParVars(parVars, parVars.branchCount, minFill)
11164	d16pickSeeds(parVars)
11165
11166	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
11167		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
11168		(parVars.count[1] < (parVars.total - parVars.minFill)) {
11169		biggestDiff = -1
11170		for index := 0; index < parVars.total; index++ {
11171			if d16notTaken == parVars.partition[index] {
11172				curRect := &parVars.branchBuf[index].rect
11173				rect0 := d16combineRect(curRect, &parVars.cover[0])
11174				rect1 := d16combineRect(curRect, &parVars.cover[1])
11175				growth0 := d16calcRectVolume(&rect0) - parVars.area[0]
11176				growth1 := d16calcRectVolume(&rect1) - parVars.area[1]
11177				diff := growth1 - growth0
11178				if diff >= 0 {
11179					group = 0
11180				} else {
11181					group = 1
11182					diff = -diff
11183				}
11184
11185				if diff > biggestDiff {
11186					biggestDiff = diff
11187					chosen = index
11188					betterGroup = group
11189				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
11190					chosen = index
11191					betterGroup = group
11192				}
11193			}
11194		}
11195		d16classify(chosen, betterGroup, parVars)
11196	}
11197
11198	// If one group too full, put remaining rects in the other
11199	if (parVars.count[0] + parVars.count[1]) < parVars.total {
11200		if parVars.count[0] >= parVars.total-parVars.minFill {
11201			group = 1
11202		} else {
11203			group = 0
11204		}
11205		for index := 0; index < parVars.total; index++ {
11206			if d16notTaken == parVars.partition[index] {
11207				d16classify(index, group, parVars)
11208			}
11209		}
11210	}
11211}
11212
11213// Copy branches from the buffer into two nodes according to the partition.
11214func d16loadNodes(nodeA, nodeB *d16nodeT, parVars *d16partitionVarsT) {
11215	for index := 0; index < parVars.total; index++ {
11216		targetNodeIndex := parVars.partition[index]
11217		targetNodes := []*d16nodeT{nodeA, nodeB}
11218
11219		// It is assured that d16addBranch here will not cause a node split.
11220		d16addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
11221	}
11222}
11223
11224// Initialize a d16partitionVarsT structure.
11225func d16initParVars(parVars *d16partitionVarsT, maxRects, minFill int) {
11226	parVars.count[0] = 0
11227	parVars.count[1] = 0
11228	parVars.area[0] = 0
11229	parVars.area[1] = 0
11230	parVars.total = maxRects
11231	parVars.minFill = minFill
11232	for index := 0; index < maxRects; index++ {
11233		parVars.partition[index] = d16notTaken
11234	}
11235}
11236
11237func d16pickSeeds(parVars *d16partitionVarsT) {
11238	var seed0, seed1 int
11239	var worst, waste float64
11240	var area [d16maxNodes + 1]float64
11241
11242	for index := 0; index < parVars.total; index++ {
11243		area[index] = d16calcRectVolume(&parVars.branchBuf[index].rect)
11244	}
11245
11246	worst = -parVars.coverSplitArea - 1
11247	for indexA := 0; indexA < parVars.total-1; indexA++ {
11248		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
11249			oneRect := d16combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
11250			waste = d16calcRectVolume(&oneRect) - area[indexA] - area[indexB]
11251			if waste > worst {
11252				worst = waste
11253				seed0 = indexA
11254				seed1 = indexB
11255			}
11256		}
11257	}
11258
11259	d16classify(seed0, 0, parVars)
11260	d16classify(seed1, 1, parVars)
11261}
11262
11263// Put a branch in one of the groups.
11264func d16classify(index, group int, parVars *d16partitionVarsT) {
11265	parVars.partition[index] = group
11266
11267	// Calculate combined rect
11268	if parVars.count[group] == 0 {
11269		parVars.cover[group] = parVars.branchBuf[index].rect
11270	} else {
11271		parVars.cover[group] = d16combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
11272	}
11273
11274	// Calculate volume of combined rect
11275	parVars.area[group] = d16calcRectVolume(&parVars.cover[group])
11276
11277	parVars.count[group]++
11278}
11279
11280// Delete a data rectangle from an index structure.
11281// Pass in a pointer to a d16rectT, the tid of the record, ptr to ptr to root node.
11282// Returns 1 if record not found, 0 if success.
11283// d16removeRect provides for eliminating the root.
11284func d16removeRect(rect *d16rectT, id interface{}, root **d16nodeT) bool {
11285	var reInsertList *d16listNodeT
11286
11287	if !d16removeRectRec(rect, id, *root, &reInsertList) {
11288		// Found and deleted a data item
11289		// Reinsert any branches from eliminated nodes
11290		for reInsertList != nil {
11291			tempNode := reInsertList.node
11292
11293			for index := 0; index < tempNode.count; index++ {
11294				// TODO go over this code. should I use (tempNode->m_level - 1)?
11295				d16insertRect(&tempNode.branch[index], root, tempNode.level)
11296			}
11297			reInsertList = reInsertList.next
11298		}
11299
11300		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
11301		// if with while? In case there is a whole branch of redundant roots...
11302		if (*root).count == 1 && (*root).isInternalNode() {
11303			tempNode := (*root).branch[0].child
11304			*root = tempNode
11305		}
11306		return false
11307	} else {
11308		return true
11309	}
11310}
11311
11312// Delete a rectangle from non-root part of an index structure.
11313// Called by d16removeRect.  Descends tree recursively,
11314// merges branches on the way back up.
11315// Returns 1 if record not found, 0 if success.
11316func d16removeRectRec(rect *d16rectT, id interface{}, node *d16nodeT, listNode **d16listNodeT) bool {
11317	if node.isInternalNode() { // not a leaf node
11318		for index := 0; index < node.count; index++ {
11319			if d16overlap(*rect, node.branch[index].rect) {
11320				if !d16removeRectRec(rect, id, node.branch[index].child, listNode) {
11321					if node.branch[index].child.count >= d16minNodes {
11322						// child removed, just resize parent rect
11323						node.branch[index].rect = d16nodeCover(node.branch[index].child)
11324					} else {
11325						// child removed, not enough entries in node, eliminate node
11326						d16reInsert(node.branch[index].child, listNode)
11327						d16disconnectBranch(node, index) // Must return after this call as count has changed
11328					}
11329					return false
11330				}
11331			}
11332		}
11333		return true
11334	} else { // A leaf node
11335		for index := 0; index < node.count; index++ {
11336			if node.branch[index].data == id {
11337				d16disconnectBranch(node, index) // Must return after this call as count has changed
11338				return false
11339			}
11340		}
11341		return true
11342	}
11343}
11344
11345// Decide whether two rectangles d16overlap.
11346func d16overlap(rectA, rectB d16rectT) bool {
11347	for index := 0; index < d16numDims; index++ {
11348		if rectA.min[index] > rectB.max[index] ||
11349			rectB.min[index] > rectA.max[index] {
11350			return false
11351		}
11352	}
11353	return true
11354}
11355
11356// Add a node to the reinsertion list.  All its branches will later
11357// be reinserted into the index structure.
11358func d16reInsert(node *d16nodeT, listNode **d16listNodeT) {
11359	newListNode := &d16listNodeT{}
11360	newListNode.node = node
11361	newListNode.next = *listNode
11362	*listNode = newListNode
11363}
11364
11365// d16search in an index tree or subtree for all data retangles that d16overlap the argument rectangle.
11366func d16search(node *d16nodeT, rect d16rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
11367	if node.isInternalNode() {
11368		// This is an internal node in the tree
11369		for index := 0; index < node.count; index++ {
11370			if d16overlap(rect, node.branch[index].rect) {
11371				var ok bool
11372				foundCount, ok = d16search(node.branch[index].child, rect, foundCount, resultCallback)
11373				if !ok {
11374					// The callback indicated to stop searching
11375					return foundCount, false
11376				}
11377			}
11378		}
11379	} else {
11380		// This is a leaf node
11381		for index := 0; index < node.count; index++ {
11382			if d16overlap(rect, node.branch[index].rect) {
11383				id := node.branch[index].data
11384				foundCount++
11385				if !resultCallback(id) {
11386					return foundCount, false // Don't continue searching
11387				}
11388
11389			}
11390		}
11391	}
11392	return foundCount, true // Continue searching
11393}
11394
11395func d17fmin(a, b float64) float64 {
11396	if a < b {
11397		return a
11398	}
11399	return b
11400}
11401func d17fmax(a, b float64) float64 {
11402	if a > b {
11403		return a
11404	}
11405	return b
11406}
11407
11408const (
11409	d17numDims            = 17
11410	d17maxNodes           = 8
11411	d17minNodes           = d17maxNodes / 2
11412	d17useSphericalVolume = true // Better split classification, may be slower on some systems
11413)
11414
11415var d17unitSphereVolume = []float64{
11416	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
11417	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
11418	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
11419	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
11420	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
11421	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
11422	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
11423}[d17numDims]
11424
11425type d17RTree struct {
11426	root *d17nodeT ///< Root of tree
11427}
11428
11429/// Minimal bounding rectangle (n-dimensional)
11430type d17rectT struct {
11431	min [d17numDims]float64 ///< Min dimensions of bounding box
11432	max [d17numDims]float64 ///< Max dimensions of bounding box
11433}
11434
11435/// May be data or may be another subtree
11436/// The parents level determines this.
11437/// If the parents level is 0, then this is data
11438type d17branchT struct {
11439	rect  d17rectT    ///< Bounds
11440	child *d17nodeT   ///< Child node
11441	data  interface{} ///< Data Id or Ptr
11442}
11443
11444/// d17nodeT for each branch level
11445type d17nodeT struct {
11446	count  int                     ///< Count
11447	level  int                     ///< Leaf is zero, others positive
11448	branch [d17maxNodes]d17branchT ///< Branch
11449}
11450
11451func (node *d17nodeT) isInternalNode() bool {
11452	return (node.level > 0) // Not a leaf, but a internal node
11453}
11454func (node *d17nodeT) isLeaf() bool {
11455	return (node.level == 0) // A leaf, contains data
11456}
11457
11458/// A link list of nodes for reinsertion after a delete operation
11459type d17listNodeT struct {
11460	next *d17listNodeT ///< Next in list
11461	node *d17nodeT     ///< Node
11462}
11463
11464const d17notTaken = -1 // indicates that position
11465
11466/// Variables for finding a split partition
11467type d17partitionVarsT struct {
11468	partition [d17maxNodes + 1]int
11469	total     int
11470	minFill   int
11471	count     [2]int
11472	cover     [2]d17rectT
11473	area      [2]float64
11474
11475	branchBuf      [d17maxNodes + 1]d17branchT
11476	branchCount    int
11477	coverSplit     d17rectT
11478	coverSplitArea float64
11479}
11480
11481func d17New() *d17RTree {
11482	// We only support machine word size simple data type eg. integer index or object pointer.
11483	// Since we are storing as union with non data branch
11484	return &d17RTree{
11485		root: &d17nodeT{},
11486	}
11487}
11488
11489/// Insert entry
11490/// \param a_min Min of bounding rect
11491/// \param a_max Max of bounding rect
11492/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
11493func (tr *d17RTree) Insert(min, max [d17numDims]float64, dataId interface{}) {
11494	var branch d17branchT
11495	branch.data = dataId
11496	for axis := 0; axis < d17numDims; axis++ {
11497		branch.rect.min[axis] = min[axis]
11498		branch.rect.max[axis] = max[axis]
11499	}
11500	d17insertRect(&branch, &tr.root, 0)
11501}
11502
11503/// Remove entry
11504/// \param a_min Min of bounding rect
11505/// \param a_max Max of bounding rect
11506/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
11507func (tr *d17RTree) Remove(min, max [d17numDims]float64, dataId interface{}) {
11508	var rect d17rectT
11509	for axis := 0; axis < d17numDims; axis++ {
11510		rect.min[axis] = min[axis]
11511		rect.max[axis] = max[axis]
11512	}
11513	d17removeRect(&rect, dataId, &tr.root)
11514}
11515
11516/// Find all within d17search rectangle
11517/// \param a_min Min of d17search bounding rect
11518/// \param a_max Max of d17search bounding rect
11519/// \param a_searchResult d17search result array.  Caller should set grow size. Function will reset, not append to array.
11520/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
11521/// \param a_context User context to pass as parameter to a_resultCallback
11522/// \return Returns the number of entries found
11523func (tr *d17RTree) Search(min, max [d17numDims]float64, resultCallback func(data interface{}) bool) int {
11524	var rect d17rectT
11525	for axis := 0; axis < d17numDims; axis++ {
11526		rect.min[axis] = min[axis]
11527		rect.max[axis] = max[axis]
11528	}
11529	foundCount, _ := d17search(tr.root, rect, 0, resultCallback)
11530	return foundCount
11531}
11532
11533/// Count the data elements in this container.  This is slow as no internal counter is maintained.
11534func (tr *d17RTree) Count() int {
11535	var count int
11536	d17countRec(tr.root, &count)
11537	return count
11538}
11539
11540/// Remove all entries from tree
11541func (tr *d17RTree) RemoveAll() {
11542	// Delete all existing nodes
11543	tr.root = &d17nodeT{}
11544}
11545
11546func d17countRec(node *d17nodeT, count *int) {
11547	if node.isInternalNode() { // not a leaf node
11548		for index := 0; index < node.count; index++ {
11549			d17countRec(node.branch[index].child, count)
11550		}
11551	} else { // A leaf node
11552		*count += node.count
11553	}
11554}
11555
11556// Inserts a new data rectangle into the index structure.
11557// Recursively descends tree, propagates splits back up.
11558// Returns 0 if node was not split.  Old node updated.
11559// If node was split, returns 1 and sets the pointer pointed to by
11560// new_node to point to the new node.  Old node updated to become one of two.
11561// The level argument specifies the number of steps up from the leaf
11562// level to insert; e.g. a data rectangle goes in at level = 0.
11563func d17insertRectRec(branch *d17branchT, node *d17nodeT, newNode **d17nodeT, level int) bool {
11564	// recurse until we reach the correct level for the new record. data records
11565	// will always be called with a_level == 0 (leaf)
11566	if node.level > level {
11567		// Still above level for insertion, go down tree recursively
11568		var otherNode *d17nodeT
11569		//var newBranch d17branchT
11570
11571		// find the optimal branch for this record
11572		index := d17pickBranch(&branch.rect, node)
11573
11574		// recursively insert this record into the picked branch
11575		childWasSplit := d17insertRectRec(branch, node.branch[index].child, &otherNode, level)
11576
11577		if !childWasSplit {
11578			// Child was not split. Merge the bounding box of the new record with the
11579			// existing bounding box
11580			node.branch[index].rect = d17combineRect(&branch.rect, &(node.branch[index].rect))
11581			return false
11582		} else {
11583			// Child was split. The old branches are now re-partitioned to two nodes
11584			// so we have to re-calculate the bounding boxes of each node
11585			node.branch[index].rect = d17nodeCover(node.branch[index].child)
11586			var newBranch d17branchT
11587			newBranch.child = otherNode
11588			newBranch.rect = d17nodeCover(otherNode)
11589
11590			// The old node is already a child of a_node. Now add the newly-created
11591			// node to a_node as well. a_node might be split because of that.
11592			return d17addBranch(&newBranch, node, newNode)
11593		}
11594	} else if node.level == level {
11595		// We have reached level for insertion. Add rect, split if necessary
11596		return d17addBranch(branch, node, newNode)
11597	} else {
11598		// Should never occur
11599		return false
11600	}
11601}
11602
11603// Insert a data rectangle into an index structure.
11604// d17insertRect provides for splitting the root;
11605// returns 1 if root was split, 0 if it was not.
11606// The level argument specifies the number of steps up from the leaf
11607// level to insert; e.g. a data rectangle goes in at level = 0.
11608// InsertRect2 does the recursion.
11609//
11610func d17insertRect(branch *d17branchT, root **d17nodeT, level int) bool {
11611	var newNode *d17nodeT
11612
11613	if d17insertRectRec(branch, *root, &newNode, level) { // Root split
11614
11615		// Grow tree taller and new root
11616		newRoot := &d17nodeT{}
11617		newRoot.level = (*root).level + 1
11618
11619		var newBranch d17branchT
11620
11621		// add old root node as a child of the new root
11622		newBranch.rect = d17nodeCover(*root)
11623		newBranch.child = *root
11624		d17addBranch(&newBranch, newRoot, nil)
11625
11626		// add the split node as a child of the new root
11627		newBranch.rect = d17nodeCover(newNode)
11628		newBranch.child = newNode
11629		d17addBranch(&newBranch, newRoot, nil)
11630
11631		// set the new root as the root node
11632		*root = newRoot
11633
11634		return true
11635	}
11636	return false
11637}
11638
11639// Find the smallest rectangle that includes all rectangles in branches of a node.
11640func d17nodeCover(node *d17nodeT) d17rectT {
11641	rect := node.branch[0].rect
11642	for index := 1; index < node.count; index++ {
11643		rect = d17combineRect(&rect, &(node.branch[index].rect))
11644	}
11645	return rect
11646}
11647
11648// Add a branch to a node.  Split the node if necessary.
11649// Returns 0 if node not split.  Old node updated.
11650// Returns 1 if node split, sets *new_node to address of new node.
11651// Old node updated, becomes one of two.
11652func d17addBranch(branch *d17branchT, node *d17nodeT, newNode **d17nodeT) bool {
11653	if node.count < d17maxNodes { // Split won't be necessary
11654		node.branch[node.count] = *branch
11655		node.count++
11656		return false
11657	} else {
11658		d17splitNode(node, branch, newNode)
11659		return true
11660	}
11661}
11662
11663// Disconnect a dependent node.
11664// Caller must return (or stop using iteration index) after this as count has changed
11665func d17disconnectBranch(node *d17nodeT, index int) {
11666	// Remove element by swapping with the last element to prevent gaps in array
11667	node.branch[index] = node.branch[node.count-1]
11668	node.branch[node.count-1].data = nil
11669	node.branch[node.count-1].child = nil
11670	node.count--
11671}
11672
11673// Pick a branch.  Pick the one that will need the smallest increase
11674// in area to accomodate the new rectangle.  This will result in the
11675// least total area for the covering rectangles in the current node.
11676// In case of a tie, pick the one which was smaller before, to get
11677// the best resolution when searching.
11678func d17pickBranch(rect *d17rectT, node *d17nodeT) int {
11679	var firstTime bool = true
11680	var increase float64
11681	var bestIncr float64 = -1
11682	var area float64
11683	var bestArea float64
11684	var best int
11685	var tempRect d17rectT
11686
11687	for index := 0; index < node.count; index++ {
11688		curRect := &node.branch[index].rect
11689		area = d17calcRectVolume(curRect)
11690		tempRect = d17combineRect(rect, curRect)
11691		increase = d17calcRectVolume(&tempRect) - area
11692		if (increase < bestIncr) || firstTime {
11693			best = index
11694			bestArea = area
11695			bestIncr = increase
11696			firstTime = false
11697		} else if (increase == bestIncr) && (area < bestArea) {
11698			best = index
11699			bestArea = area
11700			bestIncr = increase
11701		}
11702	}
11703	return best
11704}
11705
11706// Combine two rectangles into larger one containing both
11707func d17combineRect(rectA, rectB *d17rectT) d17rectT {
11708	var newRect d17rectT
11709
11710	for index := 0; index < d17numDims; index++ {
11711		newRect.min[index] = d17fmin(rectA.min[index], rectB.min[index])
11712		newRect.max[index] = d17fmax(rectA.max[index], rectB.max[index])
11713	}
11714
11715	return newRect
11716}
11717
11718// Split a node.
11719// Divides the nodes branches and the extra one between two nodes.
11720// Old node is one of the new ones, and one really new one is created.
11721// Tries more than one method for choosing a partition, uses best result.
11722func d17splitNode(node *d17nodeT, branch *d17branchT, newNode **d17nodeT) {
11723	// Could just use local here, but member or external is faster since it is reused
11724	var localVars d17partitionVarsT
11725	parVars := &localVars
11726
11727	// Load all the branches into a buffer, initialize old node
11728	d17getBranches(node, branch, parVars)
11729
11730	// Find partition
11731	d17choosePartition(parVars, d17minNodes)
11732
11733	// Create a new node to hold (about) half of the branches
11734	*newNode = &d17nodeT{}
11735	(*newNode).level = node.level
11736
11737	// Put branches from buffer into 2 nodes according to the chosen partition
11738	node.count = 0
11739	d17loadNodes(node, *newNode, parVars)
11740}
11741
11742// Calculate the n-dimensional volume of a rectangle
11743func d17rectVolume(rect *d17rectT) float64 {
11744	var volume float64 = 1
11745	for index := 0; index < d17numDims; index++ {
11746		volume *= rect.max[index] - rect.min[index]
11747	}
11748	return volume
11749}
11750
11751// The exact volume of the bounding sphere for the given d17rectT
11752func d17rectSphericalVolume(rect *d17rectT) float64 {
11753	var sumOfSquares float64 = 0
11754	var radius float64
11755
11756	for index := 0; index < d17numDims; index++ {
11757		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
11758		sumOfSquares += halfExtent * halfExtent
11759	}
11760
11761	radius = math.Sqrt(sumOfSquares)
11762
11763	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
11764	if d17numDims == 5 {
11765		return (radius * radius * radius * radius * radius * d17unitSphereVolume)
11766	} else if d17numDims == 4 {
11767		return (radius * radius * radius * radius * d17unitSphereVolume)
11768	} else if d17numDims == 3 {
11769		return (radius * radius * radius * d17unitSphereVolume)
11770	} else if d17numDims == 2 {
11771		return (radius * radius * d17unitSphereVolume)
11772	} else {
11773		return (math.Pow(radius, d17numDims) * d17unitSphereVolume)
11774	}
11775}
11776
11777// Use one of the methods to calculate retangle volume
11778func d17calcRectVolume(rect *d17rectT) float64 {
11779	if d17useSphericalVolume {
11780		return d17rectSphericalVolume(rect) // Slower but helps certain merge cases
11781	} else { // RTREE_USE_SPHERICAL_VOLUME
11782		return d17rectVolume(rect) // Faster but can cause poor merges
11783	} // RTREE_USE_SPHERICAL_VOLUME
11784}
11785
11786// Load branch buffer with branches from full node plus the extra branch.
11787func d17getBranches(node *d17nodeT, branch *d17branchT, parVars *d17partitionVarsT) {
11788	// Load the branch buffer
11789	for index := 0; index < d17maxNodes; index++ {
11790		parVars.branchBuf[index] = node.branch[index]
11791	}
11792	parVars.branchBuf[d17maxNodes] = *branch
11793	parVars.branchCount = d17maxNodes + 1
11794
11795	// Calculate rect containing all in the set
11796	parVars.coverSplit = parVars.branchBuf[0].rect
11797	for index := 1; index < d17maxNodes+1; index++ {
11798		parVars.coverSplit = d17combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
11799	}
11800	parVars.coverSplitArea = d17calcRectVolume(&parVars.coverSplit)
11801}
11802
11803// Method #0 for choosing a partition:
11804// As the seeds for the two groups, pick the two rects that would waste the
11805// most area if covered by a single rectangle, i.e. evidently the worst pair
11806// to have in the same group.
11807// Of the remaining, one at a time is chosen to be put in one of the two groups.
11808// The one chosen is the one with the greatest difference in area expansion
11809// depending on which group - the rect most strongly attracted to one group
11810// and repelled from the other.
11811// If one group gets too full (more would force other group to violate min
11812// fill requirement) then other group gets the rest.
11813// These last are the ones that can go in either group most easily.
11814func d17choosePartition(parVars *d17partitionVarsT, minFill int) {
11815	var biggestDiff float64
11816	var group, chosen, betterGroup int
11817
11818	d17initParVars(parVars, parVars.branchCount, minFill)
11819	d17pickSeeds(parVars)
11820
11821	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
11822		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
11823		(parVars.count[1] < (parVars.total - parVars.minFill)) {
11824		biggestDiff = -1
11825		for index := 0; index < parVars.total; index++ {
11826			if d17notTaken == parVars.partition[index] {
11827				curRect := &parVars.branchBuf[index].rect
11828				rect0 := d17combineRect(curRect, &parVars.cover[0])
11829				rect1 := d17combineRect(curRect, &parVars.cover[1])
11830				growth0 := d17calcRectVolume(&rect0) - parVars.area[0]
11831				growth1 := d17calcRectVolume(&rect1) - parVars.area[1]
11832				diff := growth1 - growth0
11833				if diff >= 0 {
11834					group = 0
11835				} else {
11836					group = 1
11837					diff = -diff
11838				}
11839
11840				if diff > biggestDiff {
11841					biggestDiff = diff
11842					chosen = index
11843					betterGroup = group
11844				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
11845					chosen = index
11846					betterGroup = group
11847				}
11848			}
11849		}
11850		d17classify(chosen, betterGroup, parVars)
11851	}
11852
11853	// If one group too full, put remaining rects in the other
11854	if (parVars.count[0] + parVars.count[1]) < parVars.total {
11855		if parVars.count[0] >= parVars.total-parVars.minFill {
11856			group = 1
11857		} else {
11858			group = 0
11859		}
11860		for index := 0; index < parVars.total; index++ {
11861			if d17notTaken == parVars.partition[index] {
11862				d17classify(index, group, parVars)
11863			}
11864		}
11865	}
11866}
11867
11868// Copy branches from the buffer into two nodes according to the partition.
11869func d17loadNodes(nodeA, nodeB *d17nodeT, parVars *d17partitionVarsT) {
11870	for index := 0; index < parVars.total; index++ {
11871		targetNodeIndex := parVars.partition[index]
11872		targetNodes := []*d17nodeT{nodeA, nodeB}
11873
11874		// It is assured that d17addBranch here will not cause a node split.
11875		d17addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
11876	}
11877}
11878
11879// Initialize a d17partitionVarsT structure.
11880func d17initParVars(parVars *d17partitionVarsT, maxRects, minFill int) {
11881	parVars.count[0] = 0
11882	parVars.count[1] = 0
11883	parVars.area[0] = 0
11884	parVars.area[1] = 0
11885	parVars.total = maxRects
11886	parVars.minFill = minFill
11887	for index := 0; index < maxRects; index++ {
11888		parVars.partition[index] = d17notTaken
11889	}
11890}
11891
11892func d17pickSeeds(parVars *d17partitionVarsT) {
11893	var seed0, seed1 int
11894	var worst, waste float64
11895	var area [d17maxNodes + 1]float64
11896
11897	for index := 0; index < parVars.total; index++ {
11898		area[index] = d17calcRectVolume(&parVars.branchBuf[index].rect)
11899	}
11900
11901	worst = -parVars.coverSplitArea - 1
11902	for indexA := 0; indexA < parVars.total-1; indexA++ {
11903		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
11904			oneRect := d17combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
11905			waste = d17calcRectVolume(&oneRect) - area[indexA] - area[indexB]
11906			if waste > worst {
11907				worst = waste
11908				seed0 = indexA
11909				seed1 = indexB
11910			}
11911		}
11912	}
11913
11914	d17classify(seed0, 0, parVars)
11915	d17classify(seed1, 1, parVars)
11916}
11917
11918// Put a branch in one of the groups.
11919func d17classify(index, group int, parVars *d17partitionVarsT) {
11920	parVars.partition[index] = group
11921
11922	// Calculate combined rect
11923	if parVars.count[group] == 0 {
11924		parVars.cover[group] = parVars.branchBuf[index].rect
11925	} else {
11926		parVars.cover[group] = d17combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
11927	}
11928
11929	// Calculate volume of combined rect
11930	parVars.area[group] = d17calcRectVolume(&parVars.cover[group])
11931
11932	parVars.count[group]++
11933}
11934
11935// Delete a data rectangle from an index structure.
11936// Pass in a pointer to a d17rectT, the tid of the record, ptr to ptr to root node.
11937// Returns 1 if record not found, 0 if success.
11938// d17removeRect provides for eliminating the root.
11939func d17removeRect(rect *d17rectT, id interface{}, root **d17nodeT) bool {
11940	var reInsertList *d17listNodeT
11941
11942	if !d17removeRectRec(rect, id, *root, &reInsertList) {
11943		// Found and deleted a data item
11944		// Reinsert any branches from eliminated nodes
11945		for reInsertList != nil {
11946			tempNode := reInsertList.node
11947
11948			for index := 0; index < tempNode.count; index++ {
11949				// TODO go over this code. should I use (tempNode->m_level - 1)?
11950				d17insertRect(&tempNode.branch[index], root, tempNode.level)
11951			}
11952			reInsertList = reInsertList.next
11953		}
11954
11955		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
11956		// if with while? In case there is a whole branch of redundant roots...
11957		if (*root).count == 1 && (*root).isInternalNode() {
11958			tempNode := (*root).branch[0].child
11959			*root = tempNode
11960		}
11961		return false
11962	} else {
11963		return true
11964	}
11965}
11966
11967// Delete a rectangle from non-root part of an index structure.
11968// Called by d17removeRect.  Descends tree recursively,
11969// merges branches on the way back up.
11970// Returns 1 if record not found, 0 if success.
11971func d17removeRectRec(rect *d17rectT, id interface{}, node *d17nodeT, listNode **d17listNodeT) bool {
11972	if node.isInternalNode() { // not a leaf node
11973		for index := 0; index < node.count; index++ {
11974			if d17overlap(*rect, node.branch[index].rect) {
11975				if !d17removeRectRec(rect, id, node.branch[index].child, listNode) {
11976					if node.branch[index].child.count >= d17minNodes {
11977						// child removed, just resize parent rect
11978						node.branch[index].rect = d17nodeCover(node.branch[index].child)
11979					} else {
11980						// child removed, not enough entries in node, eliminate node
11981						d17reInsert(node.branch[index].child, listNode)
11982						d17disconnectBranch(node, index) // Must return after this call as count has changed
11983					}
11984					return false
11985				}
11986			}
11987		}
11988		return true
11989	} else { // A leaf node
11990		for index := 0; index < node.count; index++ {
11991			if node.branch[index].data == id {
11992				d17disconnectBranch(node, index) // Must return after this call as count has changed
11993				return false
11994			}
11995		}
11996		return true
11997	}
11998}
11999
12000// Decide whether two rectangles d17overlap.
12001func d17overlap(rectA, rectB d17rectT) bool {
12002	for index := 0; index < d17numDims; index++ {
12003		if rectA.min[index] > rectB.max[index] ||
12004			rectB.min[index] > rectA.max[index] {
12005			return false
12006		}
12007	}
12008	return true
12009}
12010
12011// Add a node to the reinsertion list.  All its branches will later
12012// be reinserted into the index structure.
12013func d17reInsert(node *d17nodeT, listNode **d17listNodeT) {
12014	newListNode := &d17listNodeT{}
12015	newListNode.node = node
12016	newListNode.next = *listNode
12017	*listNode = newListNode
12018}
12019
12020// d17search in an index tree or subtree for all data retangles that d17overlap the argument rectangle.
12021func d17search(node *d17nodeT, rect d17rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
12022	if node.isInternalNode() {
12023		// This is an internal node in the tree
12024		for index := 0; index < node.count; index++ {
12025			if d17overlap(rect, node.branch[index].rect) {
12026				var ok bool
12027				foundCount, ok = d17search(node.branch[index].child, rect, foundCount, resultCallback)
12028				if !ok {
12029					// The callback indicated to stop searching
12030					return foundCount, false
12031				}
12032			}
12033		}
12034	} else {
12035		// This is a leaf node
12036		for index := 0; index < node.count; index++ {
12037			if d17overlap(rect, node.branch[index].rect) {
12038				id := node.branch[index].data
12039				foundCount++
12040				if !resultCallback(id) {
12041					return foundCount, false // Don't continue searching
12042				}
12043
12044			}
12045		}
12046	}
12047	return foundCount, true // Continue searching
12048}
12049
12050func d18fmin(a, b float64) float64 {
12051	if a < b {
12052		return a
12053	}
12054	return b
12055}
12056func d18fmax(a, b float64) float64 {
12057	if a > b {
12058		return a
12059	}
12060	return b
12061}
12062
12063const (
12064	d18numDims            = 18
12065	d18maxNodes           = 8
12066	d18minNodes           = d18maxNodes / 2
12067	d18useSphericalVolume = true // Better split classification, may be slower on some systems
12068)
12069
12070var d18unitSphereVolume = []float64{
12071	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
12072	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
12073	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
12074	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
12075	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
12076	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
12077	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
12078}[d18numDims]
12079
12080type d18RTree struct {
12081	root *d18nodeT ///< Root of tree
12082}
12083
12084/// Minimal bounding rectangle (n-dimensional)
12085type d18rectT struct {
12086	min [d18numDims]float64 ///< Min dimensions of bounding box
12087	max [d18numDims]float64 ///< Max dimensions of bounding box
12088}
12089
12090/// May be data or may be another subtree
12091/// The parents level determines this.
12092/// If the parents level is 0, then this is data
12093type d18branchT struct {
12094	rect  d18rectT    ///< Bounds
12095	child *d18nodeT   ///< Child node
12096	data  interface{} ///< Data Id or Ptr
12097}
12098
12099/// d18nodeT for each branch level
12100type d18nodeT struct {
12101	count  int                     ///< Count
12102	level  int                     ///< Leaf is zero, others positive
12103	branch [d18maxNodes]d18branchT ///< Branch
12104}
12105
12106func (node *d18nodeT) isInternalNode() bool {
12107	return (node.level > 0) // Not a leaf, but a internal node
12108}
12109func (node *d18nodeT) isLeaf() bool {
12110	return (node.level == 0) // A leaf, contains data
12111}
12112
12113/// A link list of nodes for reinsertion after a delete operation
12114type d18listNodeT struct {
12115	next *d18listNodeT ///< Next in list
12116	node *d18nodeT     ///< Node
12117}
12118
12119const d18notTaken = -1 // indicates that position
12120
12121/// Variables for finding a split partition
12122type d18partitionVarsT struct {
12123	partition [d18maxNodes + 1]int
12124	total     int
12125	minFill   int
12126	count     [2]int
12127	cover     [2]d18rectT
12128	area      [2]float64
12129
12130	branchBuf      [d18maxNodes + 1]d18branchT
12131	branchCount    int
12132	coverSplit     d18rectT
12133	coverSplitArea float64
12134}
12135
12136func d18New() *d18RTree {
12137	// We only support machine word size simple data type eg. integer index or object pointer.
12138	// Since we are storing as union with non data branch
12139	return &d18RTree{
12140		root: &d18nodeT{},
12141	}
12142}
12143
12144/// Insert entry
12145/// \param a_min Min of bounding rect
12146/// \param a_max Max of bounding rect
12147/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
12148func (tr *d18RTree) Insert(min, max [d18numDims]float64, dataId interface{}) {
12149	var branch d18branchT
12150	branch.data = dataId
12151	for axis := 0; axis < d18numDims; axis++ {
12152		branch.rect.min[axis] = min[axis]
12153		branch.rect.max[axis] = max[axis]
12154	}
12155	d18insertRect(&branch, &tr.root, 0)
12156}
12157
12158/// Remove entry
12159/// \param a_min Min of bounding rect
12160/// \param a_max Max of bounding rect
12161/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
12162func (tr *d18RTree) Remove(min, max [d18numDims]float64, dataId interface{}) {
12163	var rect d18rectT
12164	for axis := 0; axis < d18numDims; axis++ {
12165		rect.min[axis] = min[axis]
12166		rect.max[axis] = max[axis]
12167	}
12168	d18removeRect(&rect, dataId, &tr.root)
12169}
12170
12171/// Find all within d18search rectangle
12172/// \param a_min Min of d18search bounding rect
12173/// \param a_max Max of d18search bounding rect
12174/// \param a_searchResult d18search result array.  Caller should set grow size. Function will reset, not append to array.
12175/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
12176/// \param a_context User context to pass as parameter to a_resultCallback
12177/// \return Returns the number of entries found
12178func (tr *d18RTree) Search(min, max [d18numDims]float64, resultCallback func(data interface{}) bool) int {
12179	var rect d18rectT
12180	for axis := 0; axis < d18numDims; axis++ {
12181		rect.min[axis] = min[axis]
12182		rect.max[axis] = max[axis]
12183	}
12184	foundCount, _ := d18search(tr.root, rect, 0, resultCallback)
12185	return foundCount
12186}
12187
12188/// Count the data elements in this container.  This is slow as no internal counter is maintained.
12189func (tr *d18RTree) Count() int {
12190	var count int
12191	d18countRec(tr.root, &count)
12192	return count
12193}
12194
12195/// Remove all entries from tree
12196func (tr *d18RTree) RemoveAll() {
12197	// Delete all existing nodes
12198	tr.root = &d18nodeT{}
12199}
12200
12201func d18countRec(node *d18nodeT, count *int) {
12202	if node.isInternalNode() { // not a leaf node
12203		for index := 0; index < node.count; index++ {
12204			d18countRec(node.branch[index].child, count)
12205		}
12206	} else { // A leaf node
12207		*count += node.count
12208	}
12209}
12210
12211// Inserts a new data rectangle into the index structure.
12212// Recursively descends tree, propagates splits back up.
12213// Returns 0 if node was not split.  Old node updated.
12214// If node was split, returns 1 and sets the pointer pointed to by
12215// new_node to point to the new node.  Old node updated to become one of two.
12216// The level argument specifies the number of steps up from the leaf
12217// level to insert; e.g. a data rectangle goes in at level = 0.
12218func d18insertRectRec(branch *d18branchT, node *d18nodeT, newNode **d18nodeT, level int) bool {
12219	// recurse until we reach the correct level for the new record. data records
12220	// will always be called with a_level == 0 (leaf)
12221	if node.level > level {
12222		// Still above level for insertion, go down tree recursively
12223		var otherNode *d18nodeT
12224		//var newBranch d18branchT
12225
12226		// find the optimal branch for this record
12227		index := d18pickBranch(&branch.rect, node)
12228
12229		// recursively insert this record into the picked branch
12230		childWasSplit := d18insertRectRec(branch, node.branch[index].child, &otherNode, level)
12231
12232		if !childWasSplit {
12233			// Child was not split. Merge the bounding box of the new record with the
12234			// existing bounding box
12235			node.branch[index].rect = d18combineRect(&branch.rect, &(node.branch[index].rect))
12236			return false
12237		} else {
12238			// Child was split. The old branches are now re-partitioned to two nodes
12239			// so we have to re-calculate the bounding boxes of each node
12240			node.branch[index].rect = d18nodeCover(node.branch[index].child)
12241			var newBranch d18branchT
12242			newBranch.child = otherNode
12243			newBranch.rect = d18nodeCover(otherNode)
12244
12245			// The old node is already a child of a_node. Now add the newly-created
12246			// node to a_node as well. a_node might be split because of that.
12247			return d18addBranch(&newBranch, node, newNode)
12248		}
12249	} else if node.level == level {
12250		// We have reached level for insertion. Add rect, split if necessary
12251		return d18addBranch(branch, node, newNode)
12252	} else {
12253		// Should never occur
12254		return false
12255	}
12256}
12257
12258// Insert a data rectangle into an index structure.
12259// d18insertRect provides for splitting the root;
12260// returns 1 if root was split, 0 if it was not.
12261// The level argument specifies the number of steps up from the leaf
12262// level to insert; e.g. a data rectangle goes in at level = 0.
12263// InsertRect2 does the recursion.
12264//
12265func d18insertRect(branch *d18branchT, root **d18nodeT, level int) bool {
12266	var newNode *d18nodeT
12267
12268	if d18insertRectRec(branch, *root, &newNode, level) { // Root split
12269
12270		// Grow tree taller and new root
12271		newRoot := &d18nodeT{}
12272		newRoot.level = (*root).level + 1
12273
12274		var newBranch d18branchT
12275
12276		// add old root node as a child of the new root
12277		newBranch.rect = d18nodeCover(*root)
12278		newBranch.child = *root
12279		d18addBranch(&newBranch, newRoot, nil)
12280
12281		// add the split node as a child of the new root
12282		newBranch.rect = d18nodeCover(newNode)
12283		newBranch.child = newNode
12284		d18addBranch(&newBranch, newRoot, nil)
12285
12286		// set the new root as the root node
12287		*root = newRoot
12288
12289		return true
12290	}
12291	return false
12292}
12293
12294// Find the smallest rectangle that includes all rectangles in branches of a node.
12295func d18nodeCover(node *d18nodeT) d18rectT {
12296	rect := node.branch[0].rect
12297	for index := 1; index < node.count; index++ {
12298		rect = d18combineRect(&rect, &(node.branch[index].rect))
12299	}
12300	return rect
12301}
12302
12303// Add a branch to a node.  Split the node if necessary.
12304// Returns 0 if node not split.  Old node updated.
12305// Returns 1 if node split, sets *new_node to address of new node.
12306// Old node updated, becomes one of two.
12307func d18addBranch(branch *d18branchT, node *d18nodeT, newNode **d18nodeT) bool {
12308	if node.count < d18maxNodes { // Split won't be necessary
12309		node.branch[node.count] = *branch
12310		node.count++
12311		return false
12312	} else {
12313		d18splitNode(node, branch, newNode)
12314		return true
12315	}
12316}
12317
12318// Disconnect a dependent node.
12319// Caller must return (or stop using iteration index) after this as count has changed
12320func d18disconnectBranch(node *d18nodeT, index int) {
12321	// Remove element by swapping with the last element to prevent gaps in array
12322	node.branch[index] = node.branch[node.count-1]
12323	node.branch[node.count-1].data = nil
12324	node.branch[node.count-1].child = nil
12325	node.count--
12326}
12327
12328// Pick a branch.  Pick the one that will need the smallest increase
12329// in area to accomodate the new rectangle.  This will result in the
12330// least total area for the covering rectangles in the current node.
12331// In case of a tie, pick the one which was smaller before, to get
12332// the best resolution when searching.
12333func d18pickBranch(rect *d18rectT, node *d18nodeT) int {
12334	var firstTime bool = true
12335	var increase float64
12336	var bestIncr float64 = -1
12337	var area float64
12338	var bestArea float64
12339	var best int
12340	var tempRect d18rectT
12341
12342	for index := 0; index < node.count; index++ {
12343		curRect := &node.branch[index].rect
12344		area = d18calcRectVolume(curRect)
12345		tempRect = d18combineRect(rect, curRect)
12346		increase = d18calcRectVolume(&tempRect) - area
12347		if (increase < bestIncr) || firstTime {
12348			best = index
12349			bestArea = area
12350			bestIncr = increase
12351			firstTime = false
12352		} else if (increase == bestIncr) && (area < bestArea) {
12353			best = index
12354			bestArea = area
12355			bestIncr = increase
12356		}
12357	}
12358	return best
12359}
12360
12361// Combine two rectangles into larger one containing both
12362func d18combineRect(rectA, rectB *d18rectT) d18rectT {
12363	var newRect d18rectT
12364
12365	for index := 0; index < d18numDims; index++ {
12366		newRect.min[index] = d18fmin(rectA.min[index], rectB.min[index])
12367		newRect.max[index] = d18fmax(rectA.max[index], rectB.max[index])
12368	}
12369
12370	return newRect
12371}
12372
12373// Split a node.
12374// Divides the nodes branches and the extra one between two nodes.
12375// Old node is one of the new ones, and one really new one is created.
12376// Tries more than one method for choosing a partition, uses best result.
12377func d18splitNode(node *d18nodeT, branch *d18branchT, newNode **d18nodeT) {
12378	// Could just use local here, but member or external is faster since it is reused
12379	var localVars d18partitionVarsT
12380	parVars := &localVars
12381
12382	// Load all the branches into a buffer, initialize old node
12383	d18getBranches(node, branch, parVars)
12384
12385	// Find partition
12386	d18choosePartition(parVars, d18minNodes)
12387
12388	// Create a new node to hold (about) half of the branches
12389	*newNode = &d18nodeT{}
12390	(*newNode).level = node.level
12391
12392	// Put branches from buffer into 2 nodes according to the chosen partition
12393	node.count = 0
12394	d18loadNodes(node, *newNode, parVars)
12395}
12396
12397// Calculate the n-dimensional volume of a rectangle
12398func d18rectVolume(rect *d18rectT) float64 {
12399	var volume float64 = 1
12400	for index := 0; index < d18numDims; index++ {
12401		volume *= rect.max[index] - rect.min[index]
12402	}
12403	return volume
12404}
12405
12406// The exact volume of the bounding sphere for the given d18rectT
12407func d18rectSphericalVolume(rect *d18rectT) float64 {
12408	var sumOfSquares float64 = 0
12409	var radius float64
12410
12411	for index := 0; index < d18numDims; index++ {
12412		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
12413		sumOfSquares += halfExtent * halfExtent
12414	}
12415
12416	radius = math.Sqrt(sumOfSquares)
12417
12418	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
12419	if d18numDims == 5 {
12420		return (radius * radius * radius * radius * radius * d18unitSphereVolume)
12421	} else if d18numDims == 4 {
12422		return (radius * radius * radius * radius * d18unitSphereVolume)
12423	} else if d18numDims == 3 {
12424		return (radius * radius * radius * d18unitSphereVolume)
12425	} else if d18numDims == 2 {
12426		return (radius * radius * d18unitSphereVolume)
12427	} else {
12428		return (math.Pow(radius, d18numDims) * d18unitSphereVolume)
12429	}
12430}
12431
12432// Use one of the methods to calculate retangle volume
12433func d18calcRectVolume(rect *d18rectT) float64 {
12434	if d18useSphericalVolume {
12435		return d18rectSphericalVolume(rect) // Slower but helps certain merge cases
12436	} else { // RTREE_USE_SPHERICAL_VOLUME
12437		return d18rectVolume(rect) // Faster but can cause poor merges
12438	} // RTREE_USE_SPHERICAL_VOLUME
12439}
12440
12441// Load branch buffer with branches from full node plus the extra branch.
12442func d18getBranches(node *d18nodeT, branch *d18branchT, parVars *d18partitionVarsT) {
12443	// Load the branch buffer
12444	for index := 0; index < d18maxNodes; index++ {
12445		parVars.branchBuf[index] = node.branch[index]
12446	}
12447	parVars.branchBuf[d18maxNodes] = *branch
12448	parVars.branchCount = d18maxNodes + 1
12449
12450	// Calculate rect containing all in the set
12451	parVars.coverSplit = parVars.branchBuf[0].rect
12452	for index := 1; index < d18maxNodes+1; index++ {
12453		parVars.coverSplit = d18combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
12454	}
12455	parVars.coverSplitArea = d18calcRectVolume(&parVars.coverSplit)
12456}
12457
12458// Method #0 for choosing a partition:
12459// As the seeds for the two groups, pick the two rects that would waste the
12460// most area if covered by a single rectangle, i.e. evidently the worst pair
12461// to have in the same group.
12462// Of the remaining, one at a time is chosen to be put in one of the two groups.
12463// The one chosen is the one with the greatest difference in area expansion
12464// depending on which group - the rect most strongly attracted to one group
12465// and repelled from the other.
12466// If one group gets too full (more would force other group to violate min
12467// fill requirement) then other group gets the rest.
12468// These last are the ones that can go in either group most easily.
12469func d18choosePartition(parVars *d18partitionVarsT, minFill int) {
12470	var biggestDiff float64
12471	var group, chosen, betterGroup int
12472
12473	d18initParVars(parVars, parVars.branchCount, minFill)
12474	d18pickSeeds(parVars)
12475
12476	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
12477		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
12478		(parVars.count[1] < (parVars.total - parVars.minFill)) {
12479		biggestDiff = -1
12480		for index := 0; index < parVars.total; index++ {
12481			if d18notTaken == parVars.partition[index] {
12482				curRect := &parVars.branchBuf[index].rect
12483				rect0 := d18combineRect(curRect, &parVars.cover[0])
12484				rect1 := d18combineRect(curRect, &parVars.cover[1])
12485				growth0 := d18calcRectVolume(&rect0) - parVars.area[0]
12486				growth1 := d18calcRectVolume(&rect1) - parVars.area[1]
12487				diff := growth1 - growth0
12488				if diff >= 0 {
12489					group = 0
12490				} else {
12491					group = 1
12492					diff = -diff
12493				}
12494
12495				if diff > biggestDiff {
12496					biggestDiff = diff
12497					chosen = index
12498					betterGroup = group
12499				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
12500					chosen = index
12501					betterGroup = group
12502				}
12503			}
12504		}
12505		d18classify(chosen, betterGroup, parVars)
12506	}
12507
12508	// If one group too full, put remaining rects in the other
12509	if (parVars.count[0] + parVars.count[1]) < parVars.total {
12510		if parVars.count[0] >= parVars.total-parVars.minFill {
12511			group = 1
12512		} else {
12513			group = 0
12514		}
12515		for index := 0; index < parVars.total; index++ {
12516			if d18notTaken == parVars.partition[index] {
12517				d18classify(index, group, parVars)
12518			}
12519		}
12520	}
12521}
12522
12523// Copy branches from the buffer into two nodes according to the partition.
12524func d18loadNodes(nodeA, nodeB *d18nodeT, parVars *d18partitionVarsT) {
12525	for index := 0; index < parVars.total; index++ {
12526		targetNodeIndex := parVars.partition[index]
12527		targetNodes := []*d18nodeT{nodeA, nodeB}
12528
12529		// It is assured that d18addBranch here will not cause a node split.
12530		d18addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
12531	}
12532}
12533
12534// Initialize a d18partitionVarsT structure.
12535func d18initParVars(parVars *d18partitionVarsT, maxRects, minFill int) {
12536	parVars.count[0] = 0
12537	parVars.count[1] = 0
12538	parVars.area[0] = 0
12539	parVars.area[1] = 0
12540	parVars.total = maxRects
12541	parVars.minFill = minFill
12542	for index := 0; index < maxRects; index++ {
12543		parVars.partition[index] = d18notTaken
12544	}
12545}
12546
12547func d18pickSeeds(parVars *d18partitionVarsT) {
12548	var seed0, seed1 int
12549	var worst, waste float64
12550	var area [d18maxNodes + 1]float64
12551
12552	for index := 0; index < parVars.total; index++ {
12553		area[index] = d18calcRectVolume(&parVars.branchBuf[index].rect)
12554	}
12555
12556	worst = -parVars.coverSplitArea - 1
12557	for indexA := 0; indexA < parVars.total-1; indexA++ {
12558		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
12559			oneRect := d18combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
12560			waste = d18calcRectVolume(&oneRect) - area[indexA] - area[indexB]
12561			if waste > worst {
12562				worst = waste
12563				seed0 = indexA
12564				seed1 = indexB
12565			}
12566		}
12567	}
12568
12569	d18classify(seed0, 0, parVars)
12570	d18classify(seed1, 1, parVars)
12571}
12572
12573// Put a branch in one of the groups.
12574func d18classify(index, group int, parVars *d18partitionVarsT) {
12575	parVars.partition[index] = group
12576
12577	// Calculate combined rect
12578	if parVars.count[group] == 0 {
12579		parVars.cover[group] = parVars.branchBuf[index].rect
12580	} else {
12581		parVars.cover[group] = d18combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
12582	}
12583
12584	// Calculate volume of combined rect
12585	parVars.area[group] = d18calcRectVolume(&parVars.cover[group])
12586
12587	parVars.count[group]++
12588}
12589
12590// Delete a data rectangle from an index structure.
12591// Pass in a pointer to a d18rectT, the tid of the record, ptr to ptr to root node.
12592// Returns 1 if record not found, 0 if success.
12593// d18removeRect provides for eliminating the root.
12594func d18removeRect(rect *d18rectT, id interface{}, root **d18nodeT) bool {
12595	var reInsertList *d18listNodeT
12596
12597	if !d18removeRectRec(rect, id, *root, &reInsertList) {
12598		// Found and deleted a data item
12599		// Reinsert any branches from eliminated nodes
12600		for reInsertList != nil {
12601			tempNode := reInsertList.node
12602
12603			for index := 0; index < tempNode.count; index++ {
12604				// TODO go over this code. should I use (tempNode->m_level - 1)?
12605				d18insertRect(&tempNode.branch[index], root, tempNode.level)
12606			}
12607			reInsertList = reInsertList.next
12608		}
12609
12610		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
12611		// if with while? In case there is a whole branch of redundant roots...
12612		if (*root).count == 1 && (*root).isInternalNode() {
12613			tempNode := (*root).branch[0].child
12614			*root = tempNode
12615		}
12616		return false
12617	} else {
12618		return true
12619	}
12620}
12621
12622// Delete a rectangle from non-root part of an index structure.
12623// Called by d18removeRect.  Descends tree recursively,
12624// merges branches on the way back up.
12625// Returns 1 if record not found, 0 if success.
12626func d18removeRectRec(rect *d18rectT, id interface{}, node *d18nodeT, listNode **d18listNodeT) bool {
12627	if node.isInternalNode() { // not a leaf node
12628		for index := 0; index < node.count; index++ {
12629			if d18overlap(*rect, node.branch[index].rect) {
12630				if !d18removeRectRec(rect, id, node.branch[index].child, listNode) {
12631					if node.branch[index].child.count >= d18minNodes {
12632						// child removed, just resize parent rect
12633						node.branch[index].rect = d18nodeCover(node.branch[index].child)
12634					} else {
12635						// child removed, not enough entries in node, eliminate node
12636						d18reInsert(node.branch[index].child, listNode)
12637						d18disconnectBranch(node, index) // Must return after this call as count has changed
12638					}
12639					return false
12640				}
12641			}
12642		}
12643		return true
12644	} else { // A leaf node
12645		for index := 0; index < node.count; index++ {
12646			if node.branch[index].data == id {
12647				d18disconnectBranch(node, index) // Must return after this call as count has changed
12648				return false
12649			}
12650		}
12651		return true
12652	}
12653}
12654
12655// Decide whether two rectangles d18overlap.
12656func d18overlap(rectA, rectB d18rectT) bool {
12657	for index := 0; index < d18numDims; index++ {
12658		if rectA.min[index] > rectB.max[index] ||
12659			rectB.min[index] > rectA.max[index] {
12660			return false
12661		}
12662	}
12663	return true
12664}
12665
12666// Add a node to the reinsertion list.  All its branches will later
12667// be reinserted into the index structure.
12668func d18reInsert(node *d18nodeT, listNode **d18listNodeT) {
12669	newListNode := &d18listNodeT{}
12670	newListNode.node = node
12671	newListNode.next = *listNode
12672	*listNode = newListNode
12673}
12674
12675// d18search in an index tree or subtree for all data retangles that d18overlap the argument rectangle.
12676func d18search(node *d18nodeT, rect d18rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
12677	if node.isInternalNode() {
12678		// This is an internal node in the tree
12679		for index := 0; index < node.count; index++ {
12680			if d18overlap(rect, node.branch[index].rect) {
12681				var ok bool
12682				foundCount, ok = d18search(node.branch[index].child, rect, foundCount, resultCallback)
12683				if !ok {
12684					// The callback indicated to stop searching
12685					return foundCount, false
12686				}
12687			}
12688		}
12689	} else {
12690		// This is a leaf node
12691		for index := 0; index < node.count; index++ {
12692			if d18overlap(rect, node.branch[index].rect) {
12693				id := node.branch[index].data
12694				foundCount++
12695				if !resultCallback(id) {
12696					return foundCount, false // Don't continue searching
12697				}
12698
12699			}
12700		}
12701	}
12702	return foundCount, true // Continue searching
12703}
12704
12705func d19fmin(a, b float64) float64 {
12706	if a < b {
12707		return a
12708	}
12709	return b
12710}
12711func d19fmax(a, b float64) float64 {
12712	if a > b {
12713		return a
12714	}
12715	return b
12716}
12717
12718const (
12719	d19numDims            = 19
12720	d19maxNodes           = 8
12721	d19minNodes           = d19maxNodes / 2
12722	d19useSphericalVolume = true // Better split classification, may be slower on some systems
12723)
12724
12725var d19unitSphereVolume = []float64{
12726	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
12727	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
12728	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
12729	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
12730	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
12731	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
12732	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
12733}[d19numDims]
12734
12735type d19RTree struct {
12736	root *d19nodeT ///< Root of tree
12737}
12738
12739/// Minimal bounding rectangle (n-dimensional)
12740type d19rectT struct {
12741	min [d19numDims]float64 ///< Min dimensions of bounding box
12742	max [d19numDims]float64 ///< Max dimensions of bounding box
12743}
12744
12745/// May be data or may be another subtree
12746/// The parents level determines this.
12747/// If the parents level is 0, then this is data
12748type d19branchT struct {
12749	rect  d19rectT    ///< Bounds
12750	child *d19nodeT   ///< Child node
12751	data  interface{} ///< Data Id or Ptr
12752}
12753
12754/// d19nodeT for each branch level
12755type d19nodeT struct {
12756	count  int                     ///< Count
12757	level  int                     ///< Leaf is zero, others positive
12758	branch [d19maxNodes]d19branchT ///< Branch
12759}
12760
12761func (node *d19nodeT) isInternalNode() bool {
12762	return (node.level > 0) // Not a leaf, but a internal node
12763}
12764func (node *d19nodeT) isLeaf() bool {
12765	return (node.level == 0) // A leaf, contains data
12766}
12767
12768/// A link list of nodes for reinsertion after a delete operation
12769type d19listNodeT struct {
12770	next *d19listNodeT ///< Next in list
12771	node *d19nodeT     ///< Node
12772}
12773
12774const d19notTaken = -1 // indicates that position
12775
12776/// Variables for finding a split partition
12777type d19partitionVarsT struct {
12778	partition [d19maxNodes + 1]int
12779	total     int
12780	minFill   int
12781	count     [2]int
12782	cover     [2]d19rectT
12783	area      [2]float64
12784
12785	branchBuf      [d19maxNodes + 1]d19branchT
12786	branchCount    int
12787	coverSplit     d19rectT
12788	coverSplitArea float64
12789}
12790
12791func d19New() *d19RTree {
12792	// We only support machine word size simple data type eg. integer index or object pointer.
12793	// Since we are storing as union with non data branch
12794	return &d19RTree{
12795		root: &d19nodeT{},
12796	}
12797}
12798
12799/// Insert entry
12800/// \param a_min Min of bounding rect
12801/// \param a_max Max of bounding rect
12802/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
12803func (tr *d19RTree) Insert(min, max [d19numDims]float64, dataId interface{}) {
12804	var branch d19branchT
12805	branch.data = dataId
12806	for axis := 0; axis < d19numDims; axis++ {
12807		branch.rect.min[axis] = min[axis]
12808		branch.rect.max[axis] = max[axis]
12809	}
12810	d19insertRect(&branch, &tr.root, 0)
12811}
12812
12813/// Remove entry
12814/// \param a_min Min of bounding rect
12815/// \param a_max Max of bounding rect
12816/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
12817func (tr *d19RTree) Remove(min, max [d19numDims]float64, dataId interface{}) {
12818	var rect d19rectT
12819	for axis := 0; axis < d19numDims; axis++ {
12820		rect.min[axis] = min[axis]
12821		rect.max[axis] = max[axis]
12822	}
12823	d19removeRect(&rect, dataId, &tr.root)
12824}
12825
12826/// Find all within d19search rectangle
12827/// \param a_min Min of d19search bounding rect
12828/// \param a_max Max of d19search bounding rect
12829/// \param a_searchResult d19search result array.  Caller should set grow size. Function will reset, not append to array.
12830/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
12831/// \param a_context User context to pass as parameter to a_resultCallback
12832/// \return Returns the number of entries found
12833func (tr *d19RTree) Search(min, max [d19numDims]float64, resultCallback func(data interface{}) bool) int {
12834	var rect d19rectT
12835	for axis := 0; axis < d19numDims; axis++ {
12836		rect.min[axis] = min[axis]
12837		rect.max[axis] = max[axis]
12838	}
12839	foundCount, _ := d19search(tr.root, rect, 0, resultCallback)
12840	return foundCount
12841}
12842
12843/// Count the data elements in this container.  This is slow as no internal counter is maintained.
12844func (tr *d19RTree) Count() int {
12845	var count int
12846	d19countRec(tr.root, &count)
12847	return count
12848}
12849
12850/// Remove all entries from tree
12851func (tr *d19RTree) RemoveAll() {
12852	// Delete all existing nodes
12853	tr.root = &d19nodeT{}
12854}
12855
12856func d19countRec(node *d19nodeT, count *int) {
12857	if node.isInternalNode() { // not a leaf node
12858		for index := 0; index < node.count; index++ {
12859			d19countRec(node.branch[index].child, count)
12860		}
12861	} else { // A leaf node
12862		*count += node.count
12863	}
12864}
12865
12866// Inserts a new data rectangle into the index structure.
12867// Recursively descends tree, propagates splits back up.
12868// Returns 0 if node was not split.  Old node updated.
12869// If node was split, returns 1 and sets the pointer pointed to by
12870// new_node to point to the new node.  Old node updated to become one of two.
12871// The level argument specifies the number of steps up from the leaf
12872// level to insert; e.g. a data rectangle goes in at level = 0.
12873func d19insertRectRec(branch *d19branchT, node *d19nodeT, newNode **d19nodeT, level int) bool {
12874	// recurse until we reach the correct level for the new record. data records
12875	// will always be called with a_level == 0 (leaf)
12876	if node.level > level {
12877		// Still above level for insertion, go down tree recursively
12878		var otherNode *d19nodeT
12879		//var newBranch d19branchT
12880
12881		// find the optimal branch for this record
12882		index := d19pickBranch(&branch.rect, node)
12883
12884		// recursively insert this record into the picked branch
12885		childWasSplit := d19insertRectRec(branch, node.branch[index].child, &otherNode, level)
12886
12887		if !childWasSplit {
12888			// Child was not split. Merge the bounding box of the new record with the
12889			// existing bounding box
12890			node.branch[index].rect = d19combineRect(&branch.rect, &(node.branch[index].rect))
12891			return false
12892		} else {
12893			// Child was split. The old branches are now re-partitioned to two nodes
12894			// so we have to re-calculate the bounding boxes of each node
12895			node.branch[index].rect = d19nodeCover(node.branch[index].child)
12896			var newBranch d19branchT
12897			newBranch.child = otherNode
12898			newBranch.rect = d19nodeCover(otherNode)
12899
12900			// The old node is already a child of a_node. Now add the newly-created
12901			// node to a_node as well. a_node might be split because of that.
12902			return d19addBranch(&newBranch, node, newNode)
12903		}
12904	} else if node.level == level {
12905		// We have reached level for insertion. Add rect, split if necessary
12906		return d19addBranch(branch, node, newNode)
12907	} else {
12908		// Should never occur
12909		return false
12910	}
12911}
12912
12913// Insert a data rectangle into an index structure.
12914// d19insertRect provides for splitting the root;
12915// returns 1 if root was split, 0 if it was not.
12916// The level argument specifies the number of steps up from the leaf
12917// level to insert; e.g. a data rectangle goes in at level = 0.
12918// InsertRect2 does the recursion.
12919//
12920func d19insertRect(branch *d19branchT, root **d19nodeT, level int) bool {
12921	var newNode *d19nodeT
12922
12923	if d19insertRectRec(branch, *root, &newNode, level) { // Root split
12924
12925		// Grow tree taller and new root
12926		newRoot := &d19nodeT{}
12927		newRoot.level = (*root).level + 1
12928
12929		var newBranch d19branchT
12930
12931		// add old root node as a child of the new root
12932		newBranch.rect = d19nodeCover(*root)
12933		newBranch.child = *root
12934		d19addBranch(&newBranch, newRoot, nil)
12935
12936		// add the split node as a child of the new root
12937		newBranch.rect = d19nodeCover(newNode)
12938		newBranch.child = newNode
12939		d19addBranch(&newBranch, newRoot, nil)
12940
12941		// set the new root as the root node
12942		*root = newRoot
12943
12944		return true
12945	}
12946	return false
12947}
12948
12949// Find the smallest rectangle that includes all rectangles in branches of a node.
12950func d19nodeCover(node *d19nodeT) d19rectT {
12951	rect := node.branch[0].rect
12952	for index := 1; index < node.count; index++ {
12953		rect = d19combineRect(&rect, &(node.branch[index].rect))
12954	}
12955	return rect
12956}
12957
12958// Add a branch to a node.  Split the node if necessary.
12959// Returns 0 if node not split.  Old node updated.
12960// Returns 1 if node split, sets *new_node to address of new node.
12961// Old node updated, becomes one of two.
12962func d19addBranch(branch *d19branchT, node *d19nodeT, newNode **d19nodeT) bool {
12963	if node.count < d19maxNodes { // Split won't be necessary
12964		node.branch[node.count] = *branch
12965		node.count++
12966		return false
12967	} else {
12968		d19splitNode(node, branch, newNode)
12969		return true
12970	}
12971}
12972
12973// Disconnect a dependent node.
12974// Caller must return (or stop using iteration index) after this as count has changed
12975func d19disconnectBranch(node *d19nodeT, index int) {
12976	// Remove element by swapping with the last element to prevent gaps in array
12977	node.branch[index] = node.branch[node.count-1]
12978	node.branch[node.count-1].data = nil
12979	node.branch[node.count-1].child = nil
12980	node.count--
12981}
12982
12983// Pick a branch.  Pick the one that will need the smallest increase
12984// in area to accomodate the new rectangle.  This will result in the
12985// least total area for the covering rectangles in the current node.
12986// In case of a tie, pick the one which was smaller before, to get
12987// the best resolution when searching.
12988func d19pickBranch(rect *d19rectT, node *d19nodeT) int {
12989	var firstTime bool = true
12990	var increase float64
12991	var bestIncr float64 = -1
12992	var area float64
12993	var bestArea float64
12994	var best int
12995	var tempRect d19rectT
12996
12997	for index := 0; index < node.count; index++ {
12998		curRect := &node.branch[index].rect
12999		area = d19calcRectVolume(curRect)
13000		tempRect = d19combineRect(rect, curRect)
13001		increase = d19calcRectVolume(&tempRect) - area
13002		if (increase < bestIncr) || firstTime {
13003			best = index
13004			bestArea = area
13005			bestIncr = increase
13006			firstTime = false
13007		} else if (increase == bestIncr) && (area < bestArea) {
13008			best = index
13009			bestArea = area
13010			bestIncr = increase
13011		}
13012	}
13013	return best
13014}
13015
13016// Combine two rectangles into larger one containing both
13017func d19combineRect(rectA, rectB *d19rectT) d19rectT {
13018	var newRect d19rectT
13019
13020	for index := 0; index < d19numDims; index++ {
13021		newRect.min[index] = d19fmin(rectA.min[index], rectB.min[index])
13022		newRect.max[index] = d19fmax(rectA.max[index], rectB.max[index])
13023	}
13024
13025	return newRect
13026}
13027
13028// Split a node.
13029// Divides the nodes branches and the extra one between two nodes.
13030// Old node is one of the new ones, and one really new one is created.
13031// Tries more than one method for choosing a partition, uses best result.
13032func d19splitNode(node *d19nodeT, branch *d19branchT, newNode **d19nodeT) {
13033	// Could just use local here, but member or external is faster since it is reused
13034	var localVars d19partitionVarsT
13035	parVars := &localVars
13036
13037	// Load all the branches into a buffer, initialize old node
13038	d19getBranches(node, branch, parVars)
13039
13040	// Find partition
13041	d19choosePartition(parVars, d19minNodes)
13042
13043	// Create a new node to hold (about) half of the branches
13044	*newNode = &d19nodeT{}
13045	(*newNode).level = node.level
13046
13047	// Put branches from buffer into 2 nodes according to the chosen partition
13048	node.count = 0
13049	d19loadNodes(node, *newNode, parVars)
13050}
13051
13052// Calculate the n-dimensional volume of a rectangle
13053func d19rectVolume(rect *d19rectT) float64 {
13054	var volume float64 = 1
13055	for index := 0; index < d19numDims; index++ {
13056		volume *= rect.max[index] - rect.min[index]
13057	}
13058	return volume
13059}
13060
13061// The exact volume of the bounding sphere for the given d19rectT
13062func d19rectSphericalVolume(rect *d19rectT) float64 {
13063	var sumOfSquares float64 = 0
13064	var radius float64
13065
13066	for index := 0; index < d19numDims; index++ {
13067		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
13068		sumOfSquares += halfExtent * halfExtent
13069	}
13070
13071	radius = math.Sqrt(sumOfSquares)
13072
13073	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
13074	if d19numDims == 5 {
13075		return (radius * radius * radius * radius * radius * d19unitSphereVolume)
13076	} else if d19numDims == 4 {
13077		return (radius * radius * radius * radius * d19unitSphereVolume)
13078	} else if d19numDims == 3 {
13079		return (radius * radius * radius * d19unitSphereVolume)
13080	} else if d19numDims == 2 {
13081		return (radius * radius * d19unitSphereVolume)
13082	} else {
13083		return (math.Pow(radius, d19numDims) * d19unitSphereVolume)
13084	}
13085}
13086
13087// Use one of the methods to calculate retangle volume
13088func d19calcRectVolume(rect *d19rectT) float64 {
13089	if d19useSphericalVolume {
13090		return d19rectSphericalVolume(rect) // Slower but helps certain merge cases
13091	} else { // RTREE_USE_SPHERICAL_VOLUME
13092		return d19rectVolume(rect) // Faster but can cause poor merges
13093	} // RTREE_USE_SPHERICAL_VOLUME
13094}
13095
13096// Load branch buffer with branches from full node plus the extra branch.
13097func d19getBranches(node *d19nodeT, branch *d19branchT, parVars *d19partitionVarsT) {
13098	// Load the branch buffer
13099	for index := 0; index < d19maxNodes; index++ {
13100		parVars.branchBuf[index] = node.branch[index]
13101	}
13102	parVars.branchBuf[d19maxNodes] = *branch
13103	parVars.branchCount = d19maxNodes + 1
13104
13105	// Calculate rect containing all in the set
13106	parVars.coverSplit = parVars.branchBuf[0].rect
13107	for index := 1; index < d19maxNodes+1; index++ {
13108		parVars.coverSplit = d19combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
13109	}
13110	parVars.coverSplitArea = d19calcRectVolume(&parVars.coverSplit)
13111}
13112
13113// Method #0 for choosing a partition:
13114// As the seeds for the two groups, pick the two rects that would waste the
13115// most area if covered by a single rectangle, i.e. evidently the worst pair
13116// to have in the same group.
13117// Of the remaining, one at a time is chosen to be put in one of the two groups.
13118// The one chosen is the one with the greatest difference in area expansion
13119// depending on which group - the rect most strongly attracted to one group
13120// and repelled from the other.
13121// If one group gets too full (more would force other group to violate min
13122// fill requirement) then other group gets the rest.
13123// These last are the ones that can go in either group most easily.
13124func d19choosePartition(parVars *d19partitionVarsT, minFill int) {
13125	var biggestDiff float64
13126	var group, chosen, betterGroup int
13127
13128	d19initParVars(parVars, parVars.branchCount, minFill)
13129	d19pickSeeds(parVars)
13130
13131	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
13132		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
13133		(parVars.count[1] < (parVars.total - parVars.minFill)) {
13134		biggestDiff = -1
13135		for index := 0; index < parVars.total; index++ {
13136			if d19notTaken == parVars.partition[index] {
13137				curRect := &parVars.branchBuf[index].rect
13138				rect0 := d19combineRect(curRect, &parVars.cover[0])
13139				rect1 := d19combineRect(curRect, &parVars.cover[1])
13140				growth0 := d19calcRectVolume(&rect0) - parVars.area[0]
13141				growth1 := d19calcRectVolume(&rect1) - parVars.area[1]
13142				diff := growth1 - growth0
13143				if diff >= 0 {
13144					group = 0
13145				} else {
13146					group = 1
13147					diff = -diff
13148				}
13149
13150				if diff > biggestDiff {
13151					biggestDiff = diff
13152					chosen = index
13153					betterGroup = group
13154				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
13155					chosen = index
13156					betterGroup = group
13157				}
13158			}
13159		}
13160		d19classify(chosen, betterGroup, parVars)
13161	}
13162
13163	// If one group too full, put remaining rects in the other
13164	if (parVars.count[0] + parVars.count[1]) < parVars.total {
13165		if parVars.count[0] >= parVars.total-parVars.minFill {
13166			group = 1
13167		} else {
13168			group = 0
13169		}
13170		for index := 0; index < parVars.total; index++ {
13171			if d19notTaken == parVars.partition[index] {
13172				d19classify(index, group, parVars)
13173			}
13174		}
13175	}
13176}
13177
13178// Copy branches from the buffer into two nodes according to the partition.
13179func d19loadNodes(nodeA, nodeB *d19nodeT, parVars *d19partitionVarsT) {
13180	for index := 0; index < parVars.total; index++ {
13181		targetNodeIndex := parVars.partition[index]
13182		targetNodes := []*d19nodeT{nodeA, nodeB}
13183
13184		// It is assured that d19addBranch here will not cause a node split.
13185		d19addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
13186	}
13187}
13188
13189// Initialize a d19partitionVarsT structure.
13190func d19initParVars(parVars *d19partitionVarsT, maxRects, minFill int) {
13191	parVars.count[0] = 0
13192	parVars.count[1] = 0
13193	parVars.area[0] = 0
13194	parVars.area[1] = 0
13195	parVars.total = maxRects
13196	parVars.minFill = minFill
13197	for index := 0; index < maxRects; index++ {
13198		parVars.partition[index] = d19notTaken
13199	}
13200}
13201
13202func d19pickSeeds(parVars *d19partitionVarsT) {
13203	var seed0, seed1 int
13204	var worst, waste float64
13205	var area [d19maxNodes + 1]float64
13206
13207	for index := 0; index < parVars.total; index++ {
13208		area[index] = d19calcRectVolume(&parVars.branchBuf[index].rect)
13209	}
13210
13211	worst = -parVars.coverSplitArea - 1
13212	for indexA := 0; indexA < parVars.total-1; indexA++ {
13213		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
13214			oneRect := d19combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
13215			waste = d19calcRectVolume(&oneRect) - area[indexA] - area[indexB]
13216			if waste > worst {
13217				worst = waste
13218				seed0 = indexA
13219				seed1 = indexB
13220			}
13221		}
13222	}
13223
13224	d19classify(seed0, 0, parVars)
13225	d19classify(seed1, 1, parVars)
13226}
13227
13228// Put a branch in one of the groups.
13229func d19classify(index, group int, parVars *d19partitionVarsT) {
13230	parVars.partition[index] = group
13231
13232	// Calculate combined rect
13233	if parVars.count[group] == 0 {
13234		parVars.cover[group] = parVars.branchBuf[index].rect
13235	} else {
13236		parVars.cover[group] = d19combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
13237	}
13238
13239	// Calculate volume of combined rect
13240	parVars.area[group] = d19calcRectVolume(&parVars.cover[group])
13241
13242	parVars.count[group]++
13243}
13244
13245// Delete a data rectangle from an index structure.
13246// Pass in a pointer to a d19rectT, the tid of the record, ptr to ptr to root node.
13247// Returns 1 if record not found, 0 if success.
13248// d19removeRect provides for eliminating the root.
13249func d19removeRect(rect *d19rectT, id interface{}, root **d19nodeT) bool {
13250	var reInsertList *d19listNodeT
13251
13252	if !d19removeRectRec(rect, id, *root, &reInsertList) {
13253		// Found and deleted a data item
13254		// Reinsert any branches from eliminated nodes
13255		for reInsertList != nil {
13256			tempNode := reInsertList.node
13257
13258			for index := 0; index < tempNode.count; index++ {
13259				// TODO go over this code. should I use (tempNode->m_level - 1)?
13260				d19insertRect(&tempNode.branch[index], root, tempNode.level)
13261			}
13262			reInsertList = reInsertList.next
13263		}
13264
13265		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
13266		// if with while? In case there is a whole branch of redundant roots...
13267		if (*root).count == 1 && (*root).isInternalNode() {
13268			tempNode := (*root).branch[0].child
13269			*root = tempNode
13270		}
13271		return false
13272	} else {
13273		return true
13274	}
13275}
13276
13277// Delete a rectangle from non-root part of an index structure.
13278// Called by d19removeRect.  Descends tree recursively,
13279// merges branches on the way back up.
13280// Returns 1 if record not found, 0 if success.
13281func d19removeRectRec(rect *d19rectT, id interface{}, node *d19nodeT, listNode **d19listNodeT) bool {
13282	if node.isInternalNode() { // not a leaf node
13283		for index := 0; index < node.count; index++ {
13284			if d19overlap(*rect, node.branch[index].rect) {
13285				if !d19removeRectRec(rect, id, node.branch[index].child, listNode) {
13286					if node.branch[index].child.count >= d19minNodes {
13287						// child removed, just resize parent rect
13288						node.branch[index].rect = d19nodeCover(node.branch[index].child)
13289					} else {
13290						// child removed, not enough entries in node, eliminate node
13291						d19reInsert(node.branch[index].child, listNode)
13292						d19disconnectBranch(node, index) // Must return after this call as count has changed
13293					}
13294					return false
13295				}
13296			}
13297		}
13298		return true
13299	} else { // A leaf node
13300		for index := 0; index < node.count; index++ {
13301			if node.branch[index].data == id {
13302				d19disconnectBranch(node, index) // Must return after this call as count has changed
13303				return false
13304			}
13305		}
13306		return true
13307	}
13308}
13309
13310// Decide whether two rectangles d19overlap.
13311func d19overlap(rectA, rectB d19rectT) bool {
13312	for index := 0; index < d19numDims; index++ {
13313		if rectA.min[index] > rectB.max[index] ||
13314			rectB.min[index] > rectA.max[index] {
13315			return false
13316		}
13317	}
13318	return true
13319}
13320
13321// Add a node to the reinsertion list.  All its branches will later
13322// be reinserted into the index structure.
13323func d19reInsert(node *d19nodeT, listNode **d19listNodeT) {
13324	newListNode := &d19listNodeT{}
13325	newListNode.node = node
13326	newListNode.next = *listNode
13327	*listNode = newListNode
13328}
13329
13330// d19search in an index tree or subtree for all data retangles that d19overlap the argument rectangle.
13331func d19search(node *d19nodeT, rect d19rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
13332	if node.isInternalNode() {
13333		// This is an internal node in the tree
13334		for index := 0; index < node.count; index++ {
13335			if d19overlap(rect, node.branch[index].rect) {
13336				var ok bool
13337				foundCount, ok = d19search(node.branch[index].child, rect, foundCount, resultCallback)
13338				if !ok {
13339					// The callback indicated to stop searching
13340					return foundCount, false
13341				}
13342			}
13343		}
13344	} else {
13345		// This is a leaf node
13346		for index := 0; index < node.count; index++ {
13347			if d19overlap(rect, node.branch[index].rect) {
13348				id := node.branch[index].data
13349				foundCount++
13350				if !resultCallback(id) {
13351					return foundCount, false // Don't continue searching
13352				}
13353
13354			}
13355		}
13356	}
13357	return foundCount, true // Continue searching
13358}
13359
13360func d20fmin(a, b float64) float64 {
13361	if a < b {
13362		return a
13363	}
13364	return b
13365}
13366func d20fmax(a, b float64) float64 {
13367	if a > b {
13368		return a
13369	}
13370	return b
13371}
13372
13373const (
13374	d20numDims            = 20
13375	d20maxNodes           = 8
13376	d20minNodes           = d20maxNodes / 2
13377	d20useSphericalVolume = true // Better split classification, may be slower on some systems
13378)
13379
13380var d20unitSphereVolume = []float64{
13381	0.000000, 2.000000, 3.141593, // Dimension  0,1,2
13382	4.188790, 4.934802, 5.263789, // Dimension  3,4,5
13383	5.167713, 4.724766, 4.058712, // Dimension  6,7,8
13384	3.298509, 2.550164, 1.884104, // Dimension  9,10,11
13385	1.335263, 0.910629, 0.599265, // Dimension  12,13,14
13386	0.381443, 0.235331, 0.140981, // Dimension  15,16,17
13387	0.082146, 0.046622, 0.025807, // Dimension  18,19,20
13388}[d20numDims]
13389
13390type d20RTree struct {
13391	root *d20nodeT ///< Root of tree
13392}
13393
13394/// Minimal bounding rectangle (n-dimensional)
13395type d20rectT struct {
13396	min [d20numDims]float64 ///< Min dimensions of bounding box
13397	max [d20numDims]float64 ///< Max dimensions of bounding box
13398}
13399
13400/// May be data or may be another subtree
13401/// The parents level determines this.
13402/// If the parents level is 0, then this is data
13403type d20branchT struct {
13404	rect  d20rectT    ///< Bounds
13405	child *d20nodeT   ///< Child node
13406	data  interface{} ///< Data Id or Ptr
13407}
13408
13409/// d20nodeT for each branch level
13410type d20nodeT struct {
13411	count  int                     ///< Count
13412	level  int                     ///< Leaf is zero, others positive
13413	branch [d20maxNodes]d20branchT ///< Branch
13414}
13415
13416func (node *d20nodeT) isInternalNode() bool {
13417	return (node.level > 0) // Not a leaf, but a internal node
13418}
13419func (node *d20nodeT) isLeaf() bool {
13420	return (node.level == 0) // A leaf, contains data
13421}
13422
13423/// A link list of nodes for reinsertion after a delete operation
13424type d20listNodeT struct {
13425	next *d20listNodeT ///< Next in list
13426	node *d20nodeT     ///< Node
13427}
13428
13429const d20notTaken = -1 // indicates that position
13430
13431/// Variables for finding a split partition
13432type d20partitionVarsT struct {
13433	partition [d20maxNodes + 1]int
13434	total     int
13435	minFill   int
13436	count     [2]int
13437	cover     [2]d20rectT
13438	area      [2]float64
13439
13440	branchBuf      [d20maxNodes + 1]d20branchT
13441	branchCount    int
13442	coverSplit     d20rectT
13443	coverSplitArea float64
13444}
13445
13446func d20New() *d20RTree {
13447	// We only support machine word size simple data type eg. integer index or object pointer.
13448	// Since we are storing as union with non data branch
13449	return &d20RTree{
13450		root: &d20nodeT{},
13451	}
13452}
13453
13454/// Insert entry
13455/// \param a_min Min of bounding rect
13456/// \param a_max Max of bounding rect
13457/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
13458func (tr *d20RTree) Insert(min, max [d20numDims]float64, dataId interface{}) {
13459	var branch d20branchT
13460	branch.data = dataId
13461	for axis := 0; axis < d20numDims; axis++ {
13462		branch.rect.min[axis] = min[axis]
13463		branch.rect.max[axis] = max[axis]
13464	}
13465	d20insertRect(&branch, &tr.root, 0)
13466}
13467
13468/// Remove entry
13469/// \param a_min Min of bounding rect
13470/// \param a_max Max of bounding rect
13471/// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
13472func (tr *d20RTree) Remove(min, max [d20numDims]float64, dataId interface{}) {
13473	var rect d20rectT
13474	for axis := 0; axis < d20numDims; axis++ {
13475		rect.min[axis] = min[axis]
13476		rect.max[axis] = max[axis]
13477	}
13478	d20removeRect(&rect, dataId, &tr.root)
13479}
13480
13481/// Find all within d20search rectangle
13482/// \param a_min Min of d20search bounding rect
13483/// \param a_max Max of d20search bounding rect
13484/// \param a_searchResult d20search result array.  Caller should set grow size. Function will reset, not append to array.
13485/// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
13486/// \param a_context User context to pass as parameter to a_resultCallback
13487/// \return Returns the number of entries found
13488func (tr *d20RTree) Search(min, max [d20numDims]float64, resultCallback func(data interface{}) bool) int {
13489	var rect d20rectT
13490	for axis := 0; axis < d20numDims; axis++ {
13491		rect.min[axis] = min[axis]
13492		rect.max[axis] = max[axis]
13493	}
13494	foundCount, _ := d20search(tr.root, rect, 0, resultCallback)
13495	return foundCount
13496}
13497
13498/// Count the data elements in this container.  This is slow as no internal counter is maintained.
13499func (tr *d20RTree) Count() int {
13500	var count int
13501	d20countRec(tr.root, &count)
13502	return count
13503}
13504
13505/// Remove all entries from tree
13506func (tr *d20RTree) RemoveAll() {
13507	// Delete all existing nodes
13508	tr.root = &d20nodeT{}
13509}
13510
13511func d20countRec(node *d20nodeT, count *int) {
13512	if node.isInternalNode() { // not a leaf node
13513		for index := 0; index < node.count; index++ {
13514			d20countRec(node.branch[index].child, count)
13515		}
13516	} else { // A leaf node
13517		*count += node.count
13518	}
13519}
13520
13521// Inserts a new data rectangle into the index structure.
13522// Recursively descends tree, propagates splits back up.
13523// Returns 0 if node was not split.  Old node updated.
13524// If node was split, returns 1 and sets the pointer pointed to by
13525// new_node to point to the new node.  Old node updated to become one of two.
13526// The level argument specifies the number of steps up from the leaf
13527// level to insert; e.g. a data rectangle goes in at level = 0.
13528func d20insertRectRec(branch *d20branchT, node *d20nodeT, newNode **d20nodeT, level int) bool {
13529	// recurse until we reach the correct level for the new record. data records
13530	// will always be called with a_level == 0 (leaf)
13531	if node.level > level {
13532		// Still above level for insertion, go down tree recursively
13533		var otherNode *d20nodeT
13534		//var newBranch d20branchT
13535
13536		// find the optimal branch for this record
13537		index := d20pickBranch(&branch.rect, node)
13538
13539		// recursively insert this record into the picked branch
13540		childWasSplit := d20insertRectRec(branch, node.branch[index].child, &otherNode, level)
13541
13542		if !childWasSplit {
13543			// Child was not split. Merge the bounding box of the new record with the
13544			// existing bounding box
13545			node.branch[index].rect = d20combineRect(&branch.rect, &(node.branch[index].rect))
13546			return false
13547		} else {
13548			// Child was split. The old branches are now re-partitioned to two nodes
13549			// so we have to re-calculate the bounding boxes of each node
13550			node.branch[index].rect = d20nodeCover(node.branch[index].child)
13551			var newBranch d20branchT
13552			newBranch.child = otherNode
13553			newBranch.rect = d20nodeCover(otherNode)
13554
13555			// The old node is already a child of a_node. Now add the newly-created
13556			// node to a_node as well. a_node might be split because of that.
13557			return d20addBranch(&newBranch, node, newNode)
13558		}
13559	} else if node.level == level {
13560		// We have reached level for insertion. Add rect, split if necessary
13561		return d20addBranch(branch, node, newNode)
13562	} else {
13563		// Should never occur
13564		return false
13565	}
13566}
13567
13568// Insert a data rectangle into an index structure.
13569// d20insertRect provides for splitting the root;
13570// returns 1 if root was split, 0 if it was not.
13571// The level argument specifies the number of steps up from the leaf
13572// level to insert; e.g. a data rectangle goes in at level = 0.
13573// InsertRect2 does the recursion.
13574//
13575func d20insertRect(branch *d20branchT, root **d20nodeT, level int) bool {
13576	var newNode *d20nodeT
13577
13578	if d20insertRectRec(branch, *root, &newNode, level) { // Root split
13579
13580		// Grow tree taller and new root
13581		newRoot := &d20nodeT{}
13582		newRoot.level = (*root).level + 1
13583
13584		var newBranch d20branchT
13585
13586		// add old root node as a child of the new root
13587		newBranch.rect = d20nodeCover(*root)
13588		newBranch.child = *root
13589		d20addBranch(&newBranch, newRoot, nil)
13590
13591		// add the split node as a child of the new root
13592		newBranch.rect = d20nodeCover(newNode)
13593		newBranch.child = newNode
13594		d20addBranch(&newBranch, newRoot, nil)
13595
13596		// set the new root as the root node
13597		*root = newRoot
13598
13599		return true
13600	}
13601	return false
13602}
13603
13604// Find the smallest rectangle that includes all rectangles in branches of a node.
13605func d20nodeCover(node *d20nodeT) d20rectT {
13606	rect := node.branch[0].rect
13607	for index := 1; index < node.count; index++ {
13608		rect = d20combineRect(&rect, &(node.branch[index].rect))
13609	}
13610	return rect
13611}
13612
13613// Add a branch to a node.  Split the node if necessary.
13614// Returns 0 if node not split.  Old node updated.
13615// Returns 1 if node split, sets *new_node to address of new node.
13616// Old node updated, becomes one of two.
13617func d20addBranch(branch *d20branchT, node *d20nodeT, newNode **d20nodeT) bool {
13618	if node.count < d20maxNodes { // Split won't be necessary
13619		node.branch[node.count] = *branch
13620		node.count++
13621		return false
13622	} else {
13623		d20splitNode(node, branch, newNode)
13624		return true
13625	}
13626}
13627
13628// Disconnect a dependent node.
13629// Caller must return (or stop using iteration index) after this as count has changed
13630func d20disconnectBranch(node *d20nodeT, index int) {
13631	// Remove element by swapping with the last element to prevent gaps in array
13632	node.branch[index] = node.branch[node.count-1]
13633	node.branch[node.count-1].data = nil
13634	node.branch[node.count-1].child = nil
13635	node.count--
13636}
13637
13638// Pick a branch.  Pick the one that will need the smallest increase
13639// in area to accomodate the new rectangle.  This will result in the
13640// least total area for the covering rectangles in the current node.
13641// In case of a tie, pick the one which was smaller before, to get
13642// the best resolution when searching.
13643func d20pickBranch(rect *d20rectT, node *d20nodeT) int {
13644	var firstTime bool = true
13645	var increase float64
13646	var bestIncr float64 = -1
13647	var area float64
13648	var bestArea float64
13649	var best int
13650	var tempRect d20rectT
13651
13652	for index := 0; index < node.count; index++ {
13653		curRect := &node.branch[index].rect
13654		area = d20calcRectVolume(curRect)
13655		tempRect = d20combineRect(rect, curRect)
13656		increase = d20calcRectVolume(&tempRect) - area
13657		if (increase < bestIncr) || firstTime {
13658			best = index
13659			bestArea = area
13660			bestIncr = increase
13661			firstTime = false
13662		} else if (increase == bestIncr) && (area < bestArea) {
13663			best = index
13664			bestArea = area
13665			bestIncr = increase
13666		}
13667	}
13668	return best
13669}
13670
13671// Combine two rectangles into larger one containing both
13672func d20combineRect(rectA, rectB *d20rectT) d20rectT {
13673	var newRect d20rectT
13674
13675	for index := 0; index < d20numDims; index++ {
13676		newRect.min[index] = d20fmin(rectA.min[index], rectB.min[index])
13677		newRect.max[index] = d20fmax(rectA.max[index], rectB.max[index])
13678	}
13679
13680	return newRect
13681}
13682
13683// Split a node.
13684// Divides the nodes branches and the extra one between two nodes.
13685// Old node is one of the new ones, and one really new one is created.
13686// Tries more than one method for choosing a partition, uses best result.
13687func d20splitNode(node *d20nodeT, branch *d20branchT, newNode **d20nodeT) {
13688	// Could just use local here, but member or external is faster since it is reused
13689	var localVars d20partitionVarsT
13690	parVars := &localVars
13691
13692	// Load all the branches into a buffer, initialize old node
13693	d20getBranches(node, branch, parVars)
13694
13695	// Find partition
13696	d20choosePartition(parVars, d20minNodes)
13697
13698	// Create a new node to hold (about) half of the branches
13699	*newNode = &d20nodeT{}
13700	(*newNode).level = node.level
13701
13702	// Put branches from buffer into 2 nodes according to the chosen partition
13703	node.count = 0
13704	d20loadNodes(node, *newNode, parVars)
13705}
13706
13707// Calculate the n-dimensional volume of a rectangle
13708func d20rectVolume(rect *d20rectT) float64 {
13709	var volume float64 = 1
13710	for index := 0; index < d20numDims; index++ {
13711		volume *= rect.max[index] - rect.min[index]
13712	}
13713	return volume
13714}
13715
13716// The exact volume of the bounding sphere for the given d20rectT
13717func d20rectSphericalVolume(rect *d20rectT) float64 {
13718	var sumOfSquares float64 = 0
13719	var radius float64
13720
13721	for index := 0; index < d20numDims; index++ {
13722		halfExtent := (rect.max[index] - rect.min[index]) * 0.5
13723		sumOfSquares += halfExtent * halfExtent
13724	}
13725
13726	radius = math.Sqrt(sumOfSquares)
13727
13728	// Pow maybe slow, so test for common dims just use x*x, x*x*x.
13729	if d20numDims == 5 {
13730		return (radius * radius * radius * radius * radius * d20unitSphereVolume)
13731	} else if d20numDims == 4 {
13732		return (radius * radius * radius * radius * d20unitSphereVolume)
13733	} else if d20numDims == 3 {
13734		return (radius * radius * radius * d20unitSphereVolume)
13735	} else if d20numDims == 2 {
13736		return (radius * radius * d20unitSphereVolume)
13737	} else {
13738		return (math.Pow(radius, d20numDims) * d20unitSphereVolume)
13739	}
13740}
13741
13742// Use one of the methods to calculate retangle volume
13743func d20calcRectVolume(rect *d20rectT) float64 {
13744	if d20useSphericalVolume {
13745		return d20rectSphericalVolume(rect) // Slower but helps certain merge cases
13746	} else { // RTREE_USE_SPHERICAL_VOLUME
13747		return d20rectVolume(rect) // Faster but can cause poor merges
13748	} // RTREE_USE_SPHERICAL_VOLUME
13749}
13750
13751// Load branch buffer with branches from full node plus the extra branch.
13752func d20getBranches(node *d20nodeT, branch *d20branchT, parVars *d20partitionVarsT) {
13753	// Load the branch buffer
13754	for index := 0; index < d20maxNodes; index++ {
13755		parVars.branchBuf[index] = node.branch[index]
13756	}
13757	parVars.branchBuf[d20maxNodes] = *branch
13758	parVars.branchCount = d20maxNodes + 1
13759
13760	// Calculate rect containing all in the set
13761	parVars.coverSplit = parVars.branchBuf[0].rect
13762	for index := 1; index < d20maxNodes+1; index++ {
13763		parVars.coverSplit = d20combineRect(&parVars.coverSplit, &parVars.branchBuf[index].rect)
13764	}
13765	parVars.coverSplitArea = d20calcRectVolume(&parVars.coverSplit)
13766}
13767
13768// Method #0 for choosing a partition:
13769// As the seeds for the two groups, pick the two rects that would waste the
13770// most area if covered by a single rectangle, i.e. evidently the worst pair
13771// to have in the same group.
13772// Of the remaining, one at a time is chosen to be put in one of the two groups.
13773// The one chosen is the one with the greatest difference in area expansion
13774// depending on which group - the rect most strongly attracted to one group
13775// and repelled from the other.
13776// If one group gets too full (more would force other group to violate min
13777// fill requirement) then other group gets the rest.
13778// These last are the ones that can go in either group most easily.
13779func d20choosePartition(parVars *d20partitionVarsT, minFill int) {
13780	var biggestDiff float64
13781	var group, chosen, betterGroup int
13782
13783	d20initParVars(parVars, parVars.branchCount, minFill)
13784	d20pickSeeds(parVars)
13785
13786	for ((parVars.count[0] + parVars.count[1]) < parVars.total) &&
13787		(parVars.count[0] < (parVars.total - parVars.minFill)) &&
13788		(parVars.count[1] < (parVars.total - parVars.minFill)) {
13789		biggestDiff = -1
13790		for index := 0; index < parVars.total; index++ {
13791			if d20notTaken == parVars.partition[index] {
13792				curRect := &parVars.branchBuf[index].rect
13793				rect0 := d20combineRect(curRect, &parVars.cover[0])
13794				rect1 := d20combineRect(curRect, &parVars.cover[1])
13795				growth0 := d20calcRectVolume(&rect0) - parVars.area[0]
13796				growth1 := d20calcRectVolume(&rect1) - parVars.area[1]
13797				diff := growth1 - growth0
13798				if diff >= 0 {
13799					group = 0
13800				} else {
13801					group = 1
13802					diff = -diff
13803				}
13804
13805				if diff > biggestDiff {
13806					biggestDiff = diff
13807					chosen = index
13808					betterGroup = group
13809				} else if (diff == biggestDiff) && (parVars.count[group] < parVars.count[betterGroup]) {
13810					chosen = index
13811					betterGroup = group
13812				}
13813			}
13814		}
13815		d20classify(chosen, betterGroup, parVars)
13816	}
13817
13818	// If one group too full, put remaining rects in the other
13819	if (parVars.count[0] + parVars.count[1]) < parVars.total {
13820		if parVars.count[0] >= parVars.total-parVars.minFill {
13821			group = 1
13822		} else {
13823			group = 0
13824		}
13825		for index := 0; index < parVars.total; index++ {
13826			if d20notTaken == parVars.partition[index] {
13827				d20classify(index, group, parVars)
13828			}
13829		}
13830	}
13831}
13832
13833// Copy branches from the buffer into two nodes according to the partition.
13834func d20loadNodes(nodeA, nodeB *d20nodeT, parVars *d20partitionVarsT) {
13835	for index := 0; index < parVars.total; index++ {
13836		targetNodeIndex := parVars.partition[index]
13837		targetNodes := []*d20nodeT{nodeA, nodeB}
13838
13839		// It is assured that d20addBranch here will not cause a node split.
13840		d20addBranch(&parVars.branchBuf[index], targetNodes[targetNodeIndex], nil)
13841	}
13842}
13843
13844// Initialize a d20partitionVarsT structure.
13845func d20initParVars(parVars *d20partitionVarsT, maxRects, minFill int) {
13846	parVars.count[0] = 0
13847	parVars.count[1] = 0
13848	parVars.area[0] = 0
13849	parVars.area[1] = 0
13850	parVars.total = maxRects
13851	parVars.minFill = minFill
13852	for index := 0; index < maxRects; index++ {
13853		parVars.partition[index] = d20notTaken
13854	}
13855}
13856
13857func d20pickSeeds(parVars *d20partitionVarsT) {
13858	var seed0, seed1 int
13859	var worst, waste float64
13860	var area [d20maxNodes + 1]float64
13861
13862	for index := 0; index < parVars.total; index++ {
13863		area[index] = d20calcRectVolume(&parVars.branchBuf[index].rect)
13864	}
13865
13866	worst = -parVars.coverSplitArea - 1
13867	for indexA := 0; indexA < parVars.total-1; indexA++ {
13868		for indexB := indexA + 1; indexB < parVars.total; indexB++ {
13869			oneRect := d20combineRect(&parVars.branchBuf[indexA].rect, &parVars.branchBuf[indexB].rect)
13870			waste = d20calcRectVolume(&oneRect) - area[indexA] - area[indexB]
13871			if waste > worst {
13872				worst = waste
13873				seed0 = indexA
13874				seed1 = indexB
13875			}
13876		}
13877	}
13878
13879	d20classify(seed0, 0, parVars)
13880	d20classify(seed1, 1, parVars)
13881}
13882
13883// Put a branch in one of the groups.
13884func d20classify(index, group int, parVars *d20partitionVarsT) {
13885	parVars.partition[index] = group
13886
13887	// Calculate combined rect
13888	if parVars.count[group] == 0 {
13889		parVars.cover[group] = parVars.branchBuf[index].rect
13890	} else {
13891		parVars.cover[group] = d20combineRect(&parVars.branchBuf[index].rect, &parVars.cover[group])
13892	}
13893
13894	// Calculate volume of combined rect
13895	parVars.area[group] = d20calcRectVolume(&parVars.cover[group])
13896
13897	parVars.count[group]++
13898}
13899
13900// Delete a data rectangle from an index structure.
13901// Pass in a pointer to a d20rectT, the tid of the record, ptr to ptr to root node.
13902// Returns 1 if record not found, 0 if success.
13903// d20removeRect provides for eliminating the root.
13904func d20removeRect(rect *d20rectT, id interface{}, root **d20nodeT) bool {
13905	var reInsertList *d20listNodeT
13906
13907	if !d20removeRectRec(rect, id, *root, &reInsertList) {
13908		// Found and deleted a data item
13909		// Reinsert any branches from eliminated nodes
13910		for reInsertList != nil {
13911			tempNode := reInsertList.node
13912
13913			for index := 0; index < tempNode.count; index++ {
13914				// TODO go over this code. should I use (tempNode->m_level - 1)?
13915				d20insertRect(&tempNode.branch[index], root, tempNode.level)
13916			}
13917			reInsertList = reInsertList.next
13918		}
13919
13920		// Check for redundant root (not leaf, 1 child) and eliminate TODO replace
13921		// if with while? In case there is a whole branch of redundant roots...
13922		if (*root).count == 1 && (*root).isInternalNode() {
13923			tempNode := (*root).branch[0].child
13924			*root = tempNode
13925		}
13926		return false
13927	} else {
13928		return true
13929	}
13930}
13931
13932// Delete a rectangle from non-root part of an index structure.
13933// Called by d20removeRect.  Descends tree recursively,
13934// merges branches on the way back up.
13935// Returns 1 if record not found, 0 if success.
13936func d20removeRectRec(rect *d20rectT, id interface{}, node *d20nodeT, listNode **d20listNodeT) bool {
13937	if node.isInternalNode() { // not a leaf node
13938		for index := 0; index < node.count; index++ {
13939			if d20overlap(*rect, node.branch[index].rect) {
13940				if !d20removeRectRec(rect, id, node.branch[index].child, listNode) {
13941					if node.branch[index].child.count >= d20minNodes {
13942						// child removed, just resize parent rect
13943						node.branch[index].rect = d20nodeCover(node.branch[index].child)
13944					} else {
13945						// child removed, not enough entries in node, eliminate node
13946						d20reInsert(node.branch[index].child, listNode)
13947						d20disconnectBranch(node, index) // Must return after this call as count has changed
13948					}
13949					return false
13950				}
13951			}
13952		}
13953		return true
13954	} else { // A leaf node
13955		for index := 0; index < node.count; index++ {
13956			if node.branch[index].data == id {
13957				d20disconnectBranch(node, index) // Must return after this call as count has changed
13958				return false
13959			}
13960		}
13961		return true
13962	}
13963}
13964
13965// Decide whether two rectangles d20overlap.
13966func d20overlap(rectA, rectB d20rectT) bool {
13967	for index := 0; index < d20numDims; index++ {
13968		if rectA.min[index] > rectB.max[index] ||
13969			rectB.min[index] > rectA.max[index] {
13970			return false
13971		}
13972	}
13973	return true
13974}
13975
13976// Add a node to the reinsertion list.  All its branches will later
13977// be reinserted into the index structure.
13978func d20reInsert(node *d20nodeT, listNode **d20listNodeT) {
13979	newListNode := &d20listNodeT{}
13980	newListNode.node = node
13981	newListNode.next = *listNode
13982	*listNode = newListNode
13983}
13984
13985// d20search in an index tree or subtree for all data retangles that d20overlap the argument rectangle.
13986func d20search(node *d20nodeT, rect d20rectT, foundCount int, resultCallback func(data interface{}) bool) (int, bool) {
13987	if node.isInternalNode() {
13988		// This is an internal node in the tree
13989		for index := 0; index < node.count; index++ {
13990			if d20overlap(rect, node.branch[index].rect) {
13991				var ok bool
13992				foundCount, ok = d20search(node.branch[index].child, rect, foundCount, resultCallback)
13993				if !ok {
13994					// The callback indicated to stop searching
13995					return foundCount, false
13996				}
13997			}
13998		}
13999	} else {
14000		// This is a leaf node
14001		for index := 0; index < node.count; index++ {
14002			if d20overlap(rect, node.branch[index].rect) {
14003				id := node.branch[index].data
14004				foundCount++
14005				if !resultCallback(id) {
14006					return foundCount, false // Don't continue searching
14007				}
14008
14009			}
14010		}
14011	}
14012	return foundCount, true // Continue searching
14013}
14014