split.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /***********************************************************************
  2. * MODULE: R-Tree library
  3. *
  4. * AUTHOR(S): Antonin Guttman - original code
  5. * Daniel Green (green@superliminal.com) - major clean-up
  6. * and implementation of bounding spheres
  7. * Markus Metz - file-based and memory-based R*-tree
  8. *
  9. * PURPOSE: Multidimensional index
  10. *
  11. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General
  14. * Public License (>=v2). Read the file COPYING that comes
  15. * with GRASS for details.
  16. *
  17. ***********************************************************************/
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <assert.h>
  21. #include <float.h>
  22. /* remove after debug */
  23. #include <grass/gis.h>
  24. #include "index.h"
  25. #include "card.h"
  26. #include "split.h"
  27. #ifndef DBL_MAX
  28. #define DBL_MAX 1.797693E308 /* DBL_MAX approximation */
  29. #endif
  30. /*----------------------------------------------------------------------
  31. | Load branch buffer with branches from full node plus the extra branch.
  32. ----------------------------------------------------------------------*/
  33. static void RTreeGetBranches(struct RTree_Node *n, struct RTree_Branch *b,
  34. RectReal *CoverSplitArea, struct RTree *t)
  35. {
  36. int i, maxkids = 0;
  37. if ((n)->level > 0) {
  38. maxkids = t->nodecard;
  39. /* load the branch buffer */
  40. for (i = 0; i < maxkids; i++) {
  41. assert(t->valid_child(&(n->branch[i].child))); /* n should have every entry full */
  42. RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
  43. }
  44. }
  45. else {
  46. maxkids = t->leafcard;
  47. /* load the branch buffer */
  48. for (i = 0; i < maxkids; i++) {
  49. assert(n->branch[i].child.id); /* n should have every entry full */
  50. RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
  51. }
  52. }
  53. RTreeCopyBranch(&(t->BranchBuf[maxkids]), b, t);
  54. t->BranchCount = maxkids + 1;
  55. if (METHOD == 0) { /* quadratic split */
  56. /* calculate rect containing all in the set */
  57. RTreeCopyRect(&(t->orect), &(t->BranchBuf[0].rect), t);
  58. for (i = 1; i < maxkids + 1; i++) {
  59. RTreeExpandRect(&(t->orect), &(t->BranchBuf[i].rect), t);
  60. }
  61. *CoverSplitArea = RTreeRectSphericalVolume(&(t->orect), t);
  62. }
  63. RTreeInitNode(t, n, NODETYPE(n->level, t->fd));
  64. }
  65. /*----------------------------------------------------------------------
  66. | Put a branch in one of the groups.
  67. ----------------------------------------------------------------------*/
  68. static void RTreeClassify(int i, int group, struct RTree_PartitionVars *p,
  69. struct RTree *t)
  70. {
  71. assert(!p->taken[i]);
  72. p->partition[i] = group;
  73. p->taken[i] = TRUE;
  74. if (METHOD == 0) {
  75. if (p->count[group] == 0)
  76. RTreeCopyRect(&(p->cover[group]), &(t->BranchBuf[i].rect), t);
  77. else
  78. RTreeExpandRect(&(p->cover[group]), &(t->BranchBuf[i].rect), t);
  79. p->area[group] = RTreeRectSphericalVolume(&(p->cover[group]), t);
  80. }
  81. p->count[group]++;
  82. }
  83. /***************************************************
  84. * *
  85. * Toni Guttman's quadratic splitting method *
  86. * *
  87. ***************************************************/
  88. /*----------------------------------------------------------------------
  89. | Pick two rects from set to be the first elements of the two groups.
  90. | Pick the two that waste the most area if covered by a single
  91. | rectangle.
  92. ----------------------------------------------------------------------*/
  93. static void RTreePickSeeds(struct RTree_PartitionVars *p, RectReal CoverSplitArea, struct RTree *t)
  94. {
  95. int i, j, seed0 = 0, seed1 = 0;
  96. RectReal worst, waste, area[MAXCARD + 1];
  97. for (i = 0; i < p->total; i++)
  98. area[i] = RTreeRectSphericalVolume(&(t->BranchBuf[i]).rect, t);
  99. worst = -CoverSplitArea - 1;
  100. for (i = 0; i < p->total - 1; i++) {
  101. for (j = i + 1; j < p->total; j++) {
  102. RTreeCombineRect(&(t->BranchBuf[i].rect), &(t->BranchBuf[j].rect),
  103. &(t->orect), t);
  104. waste =
  105. RTreeRectSphericalVolume(&(t->orect), t) - area[i] - area[j];
  106. if (waste > worst) {
  107. worst = waste;
  108. seed0 = i;
  109. seed1 = j;
  110. }
  111. }
  112. }
  113. RTreeClassify(seed0, 0, p, t);
  114. RTreeClassify(seed1, 1, p, t);
  115. }
  116. /*----------------------------------------------------------------------
  117. | Copy branches from the buffer into two nodes according to the
  118. | partition.
  119. ----------------------------------------------------------------------*/
  120. static void RTreeLoadNodes(struct RTree_Node *n, struct RTree_Node *q,
  121. struct RTree_PartitionVars *p, struct RTree *t)
  122. {
  123. int i;
  124. for (i = 0; i < p->total; i++) {
  125. assert(p->partition[i] == 0 || p->partition[i] == 1);
  126. if (p->partition[i] == 0)
  127. RTreeAddBranch(&(t->BranchBuf[i]), n, NULL, NULL, NULL, NULL, t);
  128. else if (p->partition[i] == 1)
  129. RTreeAddBranch(&(t->BranchBuf[i]), q, NULL, NULL, NULL, NULL, t);
  130. }
  131. }
  132. /*----------------------------------------------------------------------
  133. | Initialize a PartitionVars structure.
  134. ----------------------------------------------------------------------*/
  135. void RTreeInitPVars(struct RTree_PartitionVars *p, int maxrects, int minfill, struct RTree *t)
  136. {
  137. int i;
  138. p->count[0] = p->count[1] = 0;
  139. if (METHOD == 0) {
  140. RTreeNullRect(&(p->cover[0]), t);
  141. RTreeNullRect(&(p->cover[1]), t);
  142. p->area[0] = p->area[1] = (RectReal) 0;
  143. }
  144. p->total = maxrects;
  145. p->minfill = minfill;
  146. for (i = 0; i < maxrects; i++) {
  147. p->taken[i] = FALSE;
  148. p->partition[i] = -1;
  149. }
  150. }
  151. /*----------------------------------------------------------------------
  152. | Print out data for a partition from PartitionVars struct.
  153. | Unused, for debugging only
  154. ----------------------------------------------------------------------*/
  155. static void RTreePrintPVars(struct RTree_PartitionVars *p, struct RTree *t, RectReal CoverSplitArea)
  156. {
  157. int i;
  158. fprintf(stdout, "\npartition:\n");
  159. for (i = 0; i < p->total; i++) {
  160. fprintf(stdout, "%3d\t", i);
  161. }
  162. fprintf(stdout, "\n");
  163. for (i = 0; i < p->total; i++) {
  164. if (p->taken[i])
  165. fprintf(stdout, " t\t");
  166. else
  167. fprintf(stdout, "\t");
  168. }
  169. fprintf(stdout, "\n");
  170. for (i = 0; i < p->total; i++) {
  171. fprintf(stdout, "%3d\t", p->partition[i]);
  172. }
  173. fprintf(stdout, "\n");
  174. fprintf(stdout, "count[0] = %d area = %f\n", p->count[0], p->area[0]);
  175. fprintf(stdout, "count[1] = %d area = %f\n", p->count[1], p->area[1]);
  176. if (p->area[0] + p->area[1] > 0) {
  177. fprintf(stdout, "total area = %f effectiveness = %3.2f\n",
  178. p->area[0] + p->area[1],
  179. (float)CoverSplitArea / (p->area[0] + p->area[1]));
  180. }
  181. fprintf(stdout, "cover[0]:\n");
  182. RTreePrintRect(&p->cover[0], 0, t);
  183. fprintf(stdout, "cover[1]:\n");
  184. RTreePrintRect(&p->cover[1], 0, t);
  185. }
  186. /*----------------------------------------------------------------------
  187. | Method #0 for choosing a partition: this is Toni Guttman's quadratic
  188. | split
  189. |
  190. | As the seeds for the two groups, pick the two rects that would waste
  191. | the most area if covered by a single rectangle, i.e. evidently the
  192. | worst pair to have in the same group. Of the remaining, one at a time
  193. | is chosen to be put in one of the two groups. The one chosen is the
  194. | one with the greatest difference in area expansion depending on which
  195. | group - the rect most strongly attracted to one group and repelled
  196. | from the other. If one group gets too full (more would force other
  197. | group to violate min fill requirement) then other group gets the rest.
  198. | These last are the ones that can go in either group most easily.
  199. ----------------------------------------------------------------------*/
  200. static void RTreeMethodZero(struct RTree_PartitionVars *p, int minfill,
  201. RectReal CoverSplitArea, struct RTree *t)
  202. {
  203. int i;
  204. RectReal biggestDiff;
  205. int group, chosen = 0, betterGroup = 0;
  206. struct RTree_Rect *r, *rect_0, *rect_1;
  207. RTreeInitPVars(p, t->BranchCount, minfill, t);
  208. RTreePickSeeds(p, CoverSplitArea, t);
  209. rect_0 = &(t->rect_0);
  210. rect_1 = &(t->rect_1);
  211. while (p->count[0] + p->count[1] < p->total
  212. && p->count[0] < p->total - p->minfill
  213. && p->count[1] < p->total - p->minfill) {
  214. biggestDiff = (RectReal) - 1.;
  215. for (i = 0; i < p->total; i++) {
  216. if (!p->taken[i]) {
  217. RectReal growth0, growth1, diff;
  218. r = &(t->BranchBuf[i].rect);
  219. RTreeCombineRect(r, &(p->cover[0]), rect_0, t);
  220. RTreeCombineRect(r, &(p->cover[1]), rect_1, t);
  221. growth0 = RTreeRectSphericalVolume(rect_0, t) - p->area[0];
  222. growth1 = RTreeRectSphericalVolume(rect_1, t) - p->area[1];
  223. diff = growth1 - growth0;
  224. if (diff >= 0)
  225. group = 0;
  226. else {
  227. group = 1;
  228. diff = -diff;
  229. }
  230. if (diff > biggestDiff) {
  231. biggestDiff = diff;
  232. chosen = i;
  233. betterGroup = group;
  234. }
  235. else if (diff == biggestDiff &&
  236. p->count[group] < p->count[betterGroup]) {
  237. chosen = i;
  238. betterGroup = group;
  239. }
  240. }
  241. }
  242. RTreeClassify(chosen, betterGroup, p, t);
  243. }
  244. /* if one group too full, put remaining rects in the other */
  245. if (p->count[0] + p->count[1] < p->total) {
  246. if (p->count[0] >= p->total - p->minfill)
  247. group = 1;
  248. else
  249. group = 0;
  250. for (i = 0; i < p->total; i++) {
  251. if (!p->taken[i])
  252. RTreeClassify(i, group, p, t);
  253. }
  254. }
  255. assert(p->count[0] + p->count[1] == p->total);
  256. assert(p->count[0] >= p->minfill && p->count[1] >= p->minfill);
  257. }
  258. /**********************************************************************
  259. * *
  260. * Norbert Beckmann's R*-tree splitting method *
  261. * *
  262. **********************************************************************/
  263. /*----------------------------------------------------------------------
  264. | swap branches
  265. ----------------------------------------------------------------------*/
  266. static void RTreeSwapBranches(struct RTree_Branch *a, struct RTree_Branch *b, struct RTree *t)
  267. {
  268. RTreeCopyBranch(&(t->c), a, t);
  269. RTreeCopyBranch(a, b, t);
  270. RTreeCopyBranch(b, &(t->c), t);
  271. }
  272. /*----------------------------------------------------------------------
  273. | compare branches for given rectangle side
  274. | return 1 if a > b
  275. | return 0 if a == b
  276. | return -1 if a < b
  277. ----------------------------------------------------------------------*/
  278. static int RTreeCompareBranches(struct RTree_Branch *a, struct RTree_Branch *b, int side)
  279. {
  280. if (a->rect.boundary[side] < b->rect.boundary[side])
  281. return -1;
  282. return (a->rect.boundary[side] > b->rect.boundary[side]);
  283. }
  284. /*----------------------------------------------------------------------
  285. | check if BranchBuf is sorted along given axis (dimension)
  286. ----------------------------------------------------------------------*/
  287. static int RTreeBranchBufIsSorted(int first, int last, int side, struct RTree *t)
  288. {
  289. int i;
  290. for (i = first; i < last; i++) {
  291. if (RTreeCompareBranches(&(t->BranchBuf[i]), &(t->BranchBuf[i + 1]), side)
  292. == 1)
  293. return 0;
  294. }
  295. return 1;
  296. }
  297. /*----------------------------------------------------------------------
  298. | partition BranchBuf for quicksort along given axis (dimension)
  299. ----------------------------------------------------------------------*/
  300. static int RTreePartitionBranchBuf(int first, int last, int side, struct RTree *t)
  301. {
  302. int pivot, mid = ((first + last) >> 1);
  303. int larger, smaller;
  304. if (last - first == 1) { /* only two items in list */
  305. if (RTreeCompareBranches
  306. (&(t->BranchBuf[first]), &(t->BranchBuf[last]), side) == 1) {
  307. RTreeSwapBranches(&(t->BranchBuf[first]), &(t->BranchBuf[last]), t);
  308. }
  309. return last;
  310. }
  311. /* larger of two */
  312. larger = pivot = mid;
  313. smaller = first;
  314. if (RTreeCompareBranches(&(t->BranchBuf[first]), &(t->BranchBuf[mid]), side)
  315. == 1) {
  316. larger = pivot = first;
  317. smaller = mid;
  318. }
  319. if (RTreeCompareBranches(&(t->BranchBuf[larger]), &(t->BranchBuf[last]), side)
  320. == 1) {
  321. /* larger is largest, get the larger of smaller and last */
  322. pivot = last;
  323. if (RTreeCompareBranches
  324. (&(t->BranchBuf[smaller]), &(t->BranchBuf[last]), side) == 1) {
  325. pivot = smaller;
  326. }
  327. }
  328. if (pivot != last) {
  329. RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[last]), t);
  330. }
  331. pivot = first;
  332. while (first < last) {
  333. if (RTreeCompareBranches
  334. (&(t->BranchBuf[first]), &(t->BranchBuf[last]), side) != 1) {
  335. if (pivot != first) {
  336. RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[first]), t);
  337. }
  338. pivot++;
  339. }
  340. ++first;
  341. }
  342. if (pivot != last) {
  343. RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[last]), t);
  344. }
  345. return pivot;
  346. }
  347. /*----------------------------------------------------------------------
  348. | quicksort BranchBuf along given side
  349. ----------------------------------------------------------------------*/
  350. static void RTreeQuicksortBranchBuf(int side, struct RTree *t)
  351. {
  352. int pivot, first, last;
  353. int s_first[MAXCARD + 1], s_last[MAXCARD + 1], stacksize;
  354. s_first[0] = 0;
  355. s_last[0] = t->BranchCount - 1;
  356. stacksize = 1;
  357. /* use stack */
  358. while (stacksize) {
  359. stacksize--;
  360. first = s_first[stacksize];
  361. last = s_last[stacksize];
  362. if (first < last) {
  363. if (!RTreeBranchBufIsSorted(first, last, side, t)) {
  364. pivot = RTreePartitionBranchBuf(first, last, side, t);
  365. s_first[stacksize] = first;
  366. s_last[stacksize] = pivot - 1;
  367. stacksize++;
  368. s_first[stacksize] = pivot + 1;
  369. s_last[stacksize] = last;
  370. stacksize++;
  371. }
  372. }
  373. }
  374. }
  375. /*----------------------------------------------------------------------
  376. | Method #1 for choosing a partition: this is the R*-tree method
  377. |
  378. | Pick the axis with the smallest margin increase (keep rectangles
  379. | square).
  380. | Along the chosen split axis, choose the distribution with the minimum
  381. | overlap-value. Resolve ties by choosing the distribution with the
  382. | minimum area-value.
  383. | If one group gets too full (more would force other group to violate min
  384. | fill requirement) then other group gets the rest.
  385. | These last are the ones that can go in either group most easily.
  386. ----------------------------------------------------------------------*/
  387. static void RTreeMethodOne(struct RTree_PartitionVars *p, int minfill,
  388. int maxkids, struct RTree *t)
  389. {
  390. int i, j, k, l, s;
  391. int axis = 0, best_axis = 0, side = 0;
  392. RectReal margin, smallest_margin = 0;
  393. struct RTree_Rect *r1, *r2;
  394. struct RTree_Rect *rect_0, *rect_1, *orect, *upperrect;
  395. int minfill1 = minfill - 1;
  396. RectReal overlap, vol, smallest_overlap = -1, smallest_vol = -1;
  397. static int *best_cut = NULL, *best_side = NULL;
  398. static int one_init = 0;
  399. if (!one_init) {
  400. best_cut = (int *)malloc(MAXLEVEL * sizeof(int));
  401. best_side = (int *)malloc(MAXLEVEL * sizeof(int));
  402. one_init = 1;
  403. }
  404. rect_0 = &(t->rect_0);
  405. rect_1 = &(t->rect_1);
  406. orect = &(t->orect);
  407. upperrect = &(t->upperrect);
  408. RTreeInitPVars(p, t->BranchCount, minfill, t);
  409. RTreeInitRect(orect, t);
  410. margin = DBL_MAX;
  411. /* choose split axis */
  412. /* For each dimension, sort rectangles first by lower boundary then
  413. * by upper boundary. Get the smallest margin. */
  414. for (i = 0; i < t->ndims; i++) {
  415. axis = i;
  416. best_cut[i] = 0;
  417. best_side[i] = 0;
  418. smallest_overlap = DBL_MAX;
  419. smallest_vol = DBL_MAX;
  420. /* first upper then lower bounds for each axis */
  421. s = 1;
  422. do {
  423. RTreeQuicksortBranchBuf(i + s * t->ndims_alloc, t);
  424. side = s;
  425. RTreeCopyRect(rect_0, &(t->BranchBuf[0].rect), t);
  426. RTreeCopyRect(upperrect, &(t->BranchBuf[maxkids].rect), t);
  427. for (j = 1; j < minfill1; j++) {
  428. r1 = &(t->BranchBuf[j].rect);
  429. RTreeExpandRect(rect_0, r1, t);
  430. r2 = &(t->BranchBuf[maxkids - j].rect);
  431. RTreeExpandRect(upperrect, r2, t);
  432. }
  433. r2 = &(t->BranchBuf[maxkids - minfill1].rect);
  434. RTreeExpandRect(upperrect, r2, t);
  435. /* check distributions for this axis, adhere the minimum node fill */
  436. for (j = minfill1; j < t->BranchCount - minfill; j++) {
  437. r1 = &(t->BranchBuf[j].rect);
  438. RTreeExpandRect(rect_0, r1, t);
  439. RTreeCopyRect(rect_1, upperrect, t);
  440. for (k = j + 1; k < t->BranchCount - minfill; k++) {
  441. r2 = &(t->BranchBuf[k].rect);
  442. RTreeExpandRect(rect_1, r2, t);
  443. }
  444. /* the margin is the sum of the lengths of the edges of a rectangle */
  445. margin =
  446. RTreeRectMargin(rect_0, t) +
  447. RTreeRectMargin(rect_1, t);
  448. /* remember best axis */
  449. if (margin <= smallest_margin) {
  450. smallest_margin = margin;
  451. best_axis = i;
  452. }
  453. /* remember best distribution for this axis */
  454. /* overlap size */
  455. overlap = 1;
  456. for (k = 0; k < t->ndims; k++) {
  457. /* no overlap */
  458. if (rect_0->boundary[k] > rect_1->boundary[k + t->ndims_alloc] ||
  459. rect_0->boundary[k + t->ndims_alloc] < rect_1->boundary[k]) {
  460. overlap = 0;
  461. break;
  462. }
  463. /* get overlap */
  464. else {
  465. if (rect_0->boundary[k] > rect_1->boundary[k])
  466. orect->boundary[k] = rect_0->boundary[k];
  467. else
  468. orect->boundary[k] = rect_1->boundary[k];
  469. l = k + t->ndims_alloc;
  470. if (rect_0->boundary[l] < rect_1->boundary[l])
  471. orect->boundary[l] = rect_0->boundary[l];
  472. else
  473. orect->boundary[l] = rect_1->boundary[l];
  474. }
  475. }
  476. if (overlap)
  477. overlap = RTreeRectVolume(orect, t);
  478. vol =
  479. RTreeRectVolume(rect_0, t) +
  480. RTreeRectVolume(rect_1, t);
  481. /* get best cut for this axis */
  482. if (overlap <= smallest_overlap) {
  483. smallest_overlap = overlap;
  484. smallest_vol = vol;
  485. best_cut[i] = j;
  486. best_side[i] = s;
  487. }
  488. else if (overlap == smallest_overlap) {
  489. /* resolve ties by minimum volume */
  490. if (vol <= smallest_vol) {
  491. smallest_vol = vol;
  492. best_cut[i] = j;
  493. best_side[i] = s;
  494. }
  495. }
  496. } /* end of distribution check */
  497. } while (s--); /* end of side check */
  498. } /* end of axis check */
  499. /* Use best distribution to classify branches */
  500. if (best_axis != axis || best_side[best_axis] != side)
  501. RTreeQuicksortBranchBuf(best_axis + best_side[best_axis] * t->ndims_alloc, t);
  502. best_cut[best_axis]++;
  503. for (i = 0; i < best_cut[best_axis]; i++)
  504. RTreeClassify(i, 0, p, t);
  505. for (i = best_cut[best_axis]; i < t->BranchCount; i++)
  506. RTreeClassify(i, 1, p, t);
  507. assert(p->count[0] + p->count[1] == p->total);
  508. assert(p->count[0] >= p->minfill && p->count[1] >= p->minfill);
  509. }
  510. /*----------------------------------------------------------------------
  511. | Split a node.
  512. | Divides the nodes branches and the extra one between two nodes.
  513. | Old node is one of the new ones, and one really new one is created.
  514. | May use quadratic split or R*-tree split.
  515. ----------------------------------------------------------------------*/
  516. void RTreeSplitNode(struct RTree_Node *n, struct RTree_Branch *b,
  517. struct RTree_Node *nn, struct RTree *t)
  518. {
  519. struct RTree_PartitionVars *p;
  520. RectReal CoverSplitArea;
  521. int level;
  522. /* load all the branches into a buffer, initialize old node */
  523. level = n->level;
  524. RTreeGetBranches(n, b, &CoverSplitArea, t);
  525. /* find partition */
  526. p = &(t->p);
  527. if (METHOD == 1) /* R* split */
  528. RTreeMethodOne(&(t->p), MINFILL(level, t), MAXKIDS(level, t), t);
  529. else
  530. RTreeMethodZero(&(t->p), MINFILL(level, t), CoverSplitArea, t);
  531. /*
  532. * put branches from buffer into 2 nodes
  533. * according to chosen partition
  534. */
  535. (nn)->level = n->level = level;
  536. RTreeLoadNodes(n, nn, p, t);
  537. assert(n->count + nn->count == p->total);
  538. }