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