[GRASS-SVN] r38654 - grass/trunk/lib/vector/rtree
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Aug 9 11:56:35 EDT 2009
Author: mmetz
Date: 2009-08-09 11:56:35 -0400 (Sun, 09 Aug 2009)
New Revision: 38654
Modified:
grass/trunk/lib/vector/rtree/index.c
grass/trunk/lib/vector/rtree/index.h
grass/trunk/lib/vector/rtree/node.c
grass/trunk/lib/vector/rtree/split.c
Log:
use union in rtree
Modified: grass/trunk/lib/vector/rtree/index.c
===================================================================
--- grass/trunk/lib/vector/rtree/index.c 2009-08-09 12:00:27 UTC (rev 38653)
+++ grass/trunk/lib/vector/rtree/index.c 2009-08-09 15:56:35 UTC (rev 38654)
@@ -54,7 +54,7 @@
new_rtree->min_node_fill = (new_rtree->nodecard - 1) / 2;
new_rtree->min_leaf_fill = (new_rtree->leafcard - 1) / 2;
- n = RTreeNewNode(new_rtree);
+ n = RTreeNewNode(new_rtree, 0);
new_rtree->n_levels = n->level = 0; /* leaf */
new_rtree->root = n;
@@ -104,11 +104,11 @@
if (s[top].sn->level > 0) { /* this is an internal node in the tree */
found = 1;
for (i = s[top].branch_id; i < t->nodecard; i++) {
- if (s[top].sn->branch[i].child &&
+ if (s[top].sn->branch[i].child.ptr &&
RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
s[top++].branch_id = i + 1;
/* add next node to stack */
- s[top].sn = n->branch[i].child;
+ s[top].sn = n->branch[i].child.ptr;
s[top].branch_id = 0;
found = 0;
break;
@@ -122,11 +122,11 @@
}
else { /* this is a leaf node */
for (i = 0; i < t->leafcard; i++) {
- if (s[top].sn->branch[i].child &&
+ if (s[top].sn->branch[i].child.id &&
RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
hitCount++;
if (shcb) { /* call the user-provided callback */
- if (!shcb((int)s[top].sn->branch[i].child, cbarg)) {
+ if (!shcb((int)s[top].sn->branch[i].child.id, cbarg)) {
/* callback wants to terminate search early */
return hitCount;
}
@@ -157,7 +157,7 @@
* The level argument specifies the number of steps up from the leaf
* level to insert; e.g. a data rectangle goes in at level = 0.
*/
-static int RTreeInsertRect2(struct Rect *r, struct Node *child, int level,
+static int RTreeInsertRect2(struct Rect *r, union Child child, int level,
struct Node **newnode, struct RTree *t,
struct ListBranch **ee, int *overflow)
{
@@ -180,7 +180,7 @@
i = RTreePickBranch(r, n, t);
s[top++].branch_id = i;
/* add next node to stack */
- s[top].sn = n->branch[i].child;
+ s[top].sn = n->branch[i].child.ptr;
}
/* Have reached level for insertion. Remove p rectangles or split */
@@ -218,8 +218,8 @@
/* get node cover of previous node */
s[top].sn->branch[i].rect = RTreeNodeCover(s[down].sn, t);
/* add new branch for new node previously added by RTreeAddBranch() */
- b.child = n2;
- b.rect = RTreeNodeCover(b.child, t);
+ b.child.ptr = n2;
+ b.rect = RTreeNodeCover(b.child.ptr, t);
/* add branch, may split node or remove branches */
cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
@@ -246,7 +246,7 @@
* level to insert; e.g. a data rectangle goes in at level = 0.
* RTreeInsertRect2 does the actual insertion.
*/
-static int RTreeInsertRect1(struct Rect *r, struct Node *child, int level,
+static int RTreeInsertRect1(struct Rect *r, union Child child, int level,
struct RTree *t)
{
struct Node *newnode;
@@ -255,26 +255,28 @@
struct ListBranch *reInsertList = NULL;
struct ListBranch *e;
int result;
- int i, overflow[50];
+ int i, overflow[MAXLEVEL];
/* R*-tree forced reinsertion: for each level only once */
- for (i = 0; i < 50; i++)
+ for (i = 0; i < MAXLEVEL; i++)
overflow[i] = 1;
result =
RTreeInsertRect2(r, child, level, &newnode, t, &reInsertList,
overflow);
+
if (result == 1) { /* root split */
/* grow a new root, & tree taller */
- newroot = RTreeNewNode(t);
- newroot->level = ++t->n_levels;
+ t->n_levels++;
+ newroot = RTreeNewNode(t, t->n_levels);
+ newroot->level = t->n_levels;
/* branch for old root */
b.rect = RTreeNodeCover(t->root, t);
- b.child = t->root;
+ b.child.ptr = t->root;
RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
/* branch for new node created by RTreeInsertRect2() */
b.rect = RTreeNodeCover(newnode, t);
- b.child = newnode;
+ b.child.ptr = newnode;
RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
/* set new root node */
t->root = newroot;
@@ -295,15 +297,16 @@
if (result == 1) { /* root split */
/* grow a new root, & tree taller */
- newroot = RTreeNewNode(t);
- newroot->level = ++t->n_levels;
+ t->n_levels++;
+ newroot = RTreeNewNode(t, t->n_levels);
+ newroot->level = t->n_levels;
/* branch for old root */
b.rect = RTreeNodeCover(t->root, t);
- b.child = t->root;
+ b.child.ptr = t->root;
RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
/* branch for new node created by RTreeInsertRect2() */
b.rect = RTreeNodeCover(newnode, t);
- b.child = newnode;
+ b.child.ptr = newnode;
RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
/* set new root node */
t->root = newroot;
@@ -323,11 +326,14 @@
*/
int RTreeInsertRect(struct Rect *r, int tid, struct RTree *t)
{
+ union Child newchild;
assert(r && t);
t->n_leafs++;
- return RTreeInsertRect1(r, (struct Node *)tid, 0, t);
+ newchild.id = tid;
+
+ return RTreeInsertRect1(r, newchild, 0, t);
}
/*
@@ -366,7 +372,7 @@
* Returns 1 if record not found, 0 if success.
*/
static int
-RTreeDeleteRect2(struct Rect *r, struct Node *child, struct RTree *t,
+RTreeDeleteRect2(struct Rect *r, union Child child, struct RTree *t,
struct ListNode **ee)
{
int i, notfound = 1;
@@ -387,11 +393,11 @@
if (s[top].sn->level > 0) {
n = s[top].sn;
for (i = s[top].branch_id; i < t->nodecard; i++) {
- if (n->branch[i].child &&
+ if (n->branch[i].child.ptr &&
RTreeOverlap(r, &(n->branch[i].rect), t)) {
s[top++].branch_id = i + 1;
/* add next node to stack */
- s[top].sn = n->branch[i].child;
+ s[top].sn = n->branch[i].child.ptr;
s[top].branch_id = 0;
notfound = 0;
@@ -408,7 +414,7 @@
}
else {
for (i = 0; i < t->leafcard; i++) {
- if (s[top].sn->branch[i].child && s[top].sn->branch[i].child == child) { /* found item */
+ if (s[top].sn->branch[i].child.id && s[top].sn->branch[i].child.id == child.id) { /* found item */
RTreeDisconnectBranch(s[top].sn, i, t);
t->n_leafs--;
notfound = 0;
@@ -439,7 +445,7 @@
}
else {
/* not enough entries in child, eliminate child node */
- RTreeReInsertNode(s[top].sn->branch[i].child, ee);
+ RTreeReInsertNode(s[top].sn->branch[i].child.ptr, ee);
RTreeDisconnectBranch(s[top].sn, i, t);
}
}
@@ -455,7 +461,7 @@
* Returns 1 if record not found, 0 if success.
* RTreeDeleteRect1 provides for eliminating the root.
*/
-static int RTreeDeleteRect1(struct Rect *r, struct Node *child,
+static int RTreeDeleteRect1(struct Rect *r, union Child child,
struct RTree *t)
{
int i, maxkids;
@@ -475,10 +481,18 @@
n = reInsertList->node;
maxkids = (n->level > 0 ? t->nodecard : t->leafcard);
for (i = 0; i < maxkids; i++) {
- if (n->branch[i].child) {
- RTreeInsertRect1(&(n->branch[i].rect),
- n->branch[i].child, n->level, t);
+ if (n->level > 0) { /* reinsert node branches */
+ if (n->branch[i].child.ptr) {
+ RTreeInsertRect1(&(n->branch[i].rect),
+ n->branch[i].child, n->level, t);
+ }
}
+ else { /* reinsert leaf branches */
+ if (n->branch[i].child.id) {
+ RTreeInsertRect1(&(n->branch[i].rect),
+ n->branch[i].child, n->level, t);
+ }
+ }
}
e = reInsertList;
reInsertList = reInsertList->next;
@@ -491,10 +505,10 @@
if (n->count == 1 && n->level > 0) {
for (i = 0; i < t->nodecard; i++) {
- if (n->branch[i].child)
+ if (n->branch[i].child.ptr)
break;
}
- t->root = n->branch[i].child;
+ t->root = n->branch[i].child.ptr;
RTreeFreeNode(n);
}
return 0;
@@ -518,5 +532,9 @@
*/
int RTreeDeleteRect(struct Rect *r, int tid, struct RTree *t)
{
- return RTreeDeleteRect1(r, (struct Node *)tid, t);
+ union Child child;
+
+ child.id = tid;
+
+ return RTreeDeleteRect1(r, child, t);
}
Modified: grass/trunk/lib/vector/rtree/index.h
===================================================================
--- grass/trunk/lib/vector/rtree/index.h 2009-08-09 12:00:27 UTC (rev 38653)
+++ grass/trunk/lib/vector/rtree/index.h 2009-08-09 15:56:35 UTC (rev 38654)
@@ -60,10 +60,16 @@
struct Node; /* node for memory based index */
+union Child
+{
+ int id; /* child id */
+ struct Node *ptr; /* pointer to child node */
+};
+
struct Branch /* branch for memory based index */
{
struct Rect rect;
- struct Node *child; /* pointer to child node */
+ union Child child;
};
struct Node /* node for memory based index */
@@ -128,8 +134,8 @@
extern struct RTree *RTreeNewIndex(int);
void RTreeFreeIndex(struct RTree *);
/* node.c */
-extern struct Node *RTreeNewNode(struct RTree *);
-extern void RTreeInitNode(struct Node *);
+extern struct Node *RTreeNewNode(struct RTree *, int);
+extern void RTreeInitNode(struct Node *, int);
extern void RTreeFreeNode(struct Node *);
extern void RTreeDestroyNode(struct Node *, int);
extern struct Rect RTreeNodeCover(struct Node *, struct RTree *);
Modified: grass/trunk/lib/vector/rtree/node.c
===================================================================
--- grass/trunk/lib/vector/rtree/node.c 2009-08-09 12:00:27 UTC (rev 38653)
+++ grass/trunk/lib/vector/rtree/node.c 2009-08-09 15:56:35 UTC (rev 38654)
@@ -30,33 +30,51 @@
RectReal distance; /* distance to node center */
};
-/* Initialize one branch cell in a node. */
-static void RTreeInitBranch(struct Branch *b)
+/* Initialize one branch cell in an internal node. */
+static void RTreeInitNodeBranch(struct Branch *b)
{
RTreeInitRect(&(b->rect));
- b->child = NULL;
+ b->child.ptr = NULL;
}
+/* Initialize one branch cell in a leaf node. */
+static void RTreeInitLeafBranch(struct Branch *b)
+{
+ RTreeInitRect(&(b->rect));
+ b->child.id = 0;
+
+}
+
+static void (*RTreeInitBranch[2]) () = {
+ RTreeInitLeafBranch, RTreeInitNodeBranch
+};
+
/* Initialize a Node structure. */
-void RTreeInitNode(struct Node *n)
+void RTreeInitNode(struct Node *n, int level)
{
int i;
n->count = 0;
n->level = -1;
- for (i = 0; i < MAXCARD; i++)
- RTreeInitBranch(&(n->branch[i]));
+ if (level > 0) {
+ for (i = 0; i < MAXCARD; i++)
+ RTreeInitNodeBranch(&(n->branch[i]));
+ }
+ else {
+ for (i = 0; i < MAXCARD; i++)
+ RTreeInitLeafBranch(&(n->branch[i]));
+ }
}
/* Make a new node and initialize to have all branch cells empty. */
-struct Node *RTreeNewNode(struct RTree *t)
+struct Node *RTreeNewNode(struct RTree *t, int level)
{
struct Node *n;
n = (struct Node *)malloc((size_t) t->nodesize);
assert(n);
- RTreeInitNode(n);
+ RTreeInitNode(n, level);
return n;
}
@@ -72,23 +90,36 @@
*/
struct Rect RTreeNodeCover(struct Node *n, struct RTree *t)
{
- int i, first_time = 1, maxkids;
+ int i, first_time = 1;
struct Rect r;
assert(n);
- maxkids = ((n)->level > 0 ? t->nodecard : t->leafcard);
-
RTreeInitRect(&r);
- for (i = 0; i < maxkids; i++)
- if (n->branch[i].child) {
- if (first_time) {
- r = n->branch[i].rect;
- first_time = 0;
+ if ((n)->level > 0) { /* internal node */
+ for (i = 0; i < t->nodecard; i++) {
+ if (n->branch[i].child.ptr) {
+ if (first_time) {
+ r = n->branch[i].rect;
+ first_time = 0;
+ }
+ else
+ r = RTreeCombineRect(&r, &(n->branch[i].rect), t);
}
- else
- r = RTreeCombineRect(&r, &(n->branch[i].rect), t);
}
+ }
+ else { /* leaf */
+ for (i = 0; i < t->leafcard; i++) {
+ if (n->branch[i].child.id) {
+ if (first_time) {
+ r = n->branch[i].rect;
+ first_time = 0;
+ }
+ else
+ r = RTreeCombineRect(&r, &(n->branch[i].rect), t);
+ }
+ }
+ }
return r;
}
@@ -120,7 +151,7 @@
/* get the branch that will overlap with the smallest number of
* sibling branches when including the new rectangle */
for (i = 0; i < t->nodecard; i++) {
- if (n->branch[i].child) {
+ if (n->branch[i].child.ptr) {
rr = &n->branch[i].rect;
tmp_rect = RTreeCombineRect(r, rr, t);
area = RTreeRectSphericalVolume(rr, t);
@@ -180,7 +211,7 @@
return RTreePickBranch1(r, n, t);
for (i = 0; i < t->nodecard; i++) {
- if (n->branch[i].child) {
+ if (n->branch[i].child.ptr) {
rr = &n->branch[i].rect;
area = RTreeRectSphericalVolume(rr, t);
tmp_rect = RTreeCombineRect(r, rr, t);
@@ -203,14 +234,17 @@
/* Disconnect a dependent node. */
void RTreeDisconnectBranch(struct Node *n, int i, struct RTree *t)
{
- int maxkids;
+ if ((n)->level > 0) {
+ assert(n && i >= 0 && i < t->nodecard);
+ assert(n->branch[i].child.ptr);
+ RTreeInitNodeBranch(&(n->branch[i]));
+ }
+ else {
+ assert(n && i >= 0 && i < t->leafcard);
+ assert(n->branch[i].child.id);
+ RTreeInitLeafBranch(&(n->branch[i]));
+ }
- maxkids = ((n)->level > 0 ? t->nodecard : t->leafcard);
-
- assert(n && i >= 0 && i < maxkids);
- assert(n->branch[i].child);
-
- RTreeInitBranch(&(n->branch[i]));
n->count--;
}
@@ -222,8 +256,8 @@
if (n->level > 0) { /* it is not leaf -> destroy childs */
for (i = 0; i < nodes; i++) {
- if (n->branch[i].child) {
- RTreeDestroyNode(n->branch[i].child, nodes);
+ if (n->branch[i].child.ptr) {
+ RTreeDestroyNode(n->branch[i].child.ptr, nodes);
}
}
}
@@ -395,12 +429,20 @@
struct ListBranch **ee, struct Rect *cover,
struct RTree *t)
{
- int i, j, maxkids;
+ int i, j, maxkids, is_node;
RectReal center_n[NUMDIMS], center_r, delta;
struct Branch branchbuf[MAXCARD + 1];
struct dist rdist[MAXCARD + 1];
- maxkids = t->nodecard;
+ if ((n)->level > 0) {
+ maxkids = t->nodecard;
+ is_node = 1;
+ }
+ else {
+ maxkids = t->leafcard;
+ is_node = 0;
+ }
+ maxkids = (n)->level > 0 ? t->nodecard : t->leafcard;
assert(n->count == maxkids); /* must be full */
@@ -422,7 +464,7 @@
rdist[i].distance += delta * delta;
}
- RTreeInitBranch(&(n->branch[i]));
+ RTreeInitBranch[is_node](&(n->branch[i]));
}
/* new branch */
@@ -433,7 +475,7 @@
/* quicksort dist */
RTreeQuicksortDist(rdist, maxkids);
- /* put largest three in branch list */
+ /* put largest three in branch list, farthest from center first */
for (i = 0; i < FORCECARD; i++) {
RTreeReInsertBranch(branchbuf[rdist[maxkids - i].id], n->level, ee);
}
@@ -449,6 +491,7 @@
* Returns 0 if node not split. Old node updated.
* Returns 1 if node split, sets *new_node to address of new node.
* Old node updated, becomes one of two.
+ * Returns 2 if branches wereremoved for forced reinsertion
*/
int RTreeAddBranch(struct Branch *b, struct Node *n,
struct Node **new_node, struct ListBranch **ee,
@@ -462,14 +505,26 @@
maxkids = ((n)->level > 0 ? t->nodecard : t->leafcard);
if (n->count < maxkids) { /* split won't be necessary */
- for (i = 0; i < maxkids; i++) { /* find empty branch */
- if (n->branch[i].child == 0) {
- n->branch[i] = *b;
- n->count++;
- break;
+ if ((n)->level > 0) { /* internal node */
+ for (i = 0; i < t->nodecard; i++) { /* find empty branch */
+ if (n->branch[i].child.ptr == NULL) {
+ n->branch[i] = *b;
+ n->count++;
+ break;
+ }
}
+ return 0;
}
- return 0;
+ else if ((n)->level == 0) { /* leaf */
+ for (i = 0; i < t->leafcard; i++) { /* find empty branch */
+ if (n->branch[i].child.id == 0) {
+ n->branch[i] = *b;
+ n->count++;
+ break;
+ }
+ }
+ return 0;
+ }
}
else {
if (n->level < t->n_levels && overflow[n->level]) {
@@ -479,11 +534,15 @@
return 2;
}
else {
- *new_node = RTreeNewNode(t);
+ *new_node = RTreeNewNode(t, (n)->level);
RTreeSplitNode(n, b, *new_node, t);
return 1;
}
}
+
+ /* should not be reached */
+ assert(0);
+ return -1;
}
/*
@@ -501,7 +560,7 @@
static void RTreePrintBranch(struct Branch *b, int depth, struct RTree *t)
{
RTreePrintRect(&(b->rect), depth);
- RTreePrintNode(b->child, depth, t);
+ RTreePrintNode(b->child.ptr, depth, t);
}
/* Print out the data in a node. */
@@ -527,8 +586,8 @@
if (n->level == 0) {
RTreeTabIn(depth);
RTreePrintRect(&(n->branch[i].rect), depth);
- fprintf(stdout, "\t%d: data id = %o\n", i,
- (unsigned)n->branch[i].child);
+ fprintf(stdout, "\t%d: data id = %d\n", i,
+ n->branch[i].child.id);
}
else {
RTreeTabIn(depth);
Modified: grass/trunk/lib/vector/rtree/split.c
===================================================================
--- grass/trunk/lib/vector/rtree/split.c 2009-08-09 12:00:27 UTC (rev 38653)
+++ grass/trunk/lib/vector/rtree/split.c 2009-08-09 15:56:35 UTC (rev 38654)
@@ -19,10 +19,15 @@
#include <stdio.h>
#include <assert.h>
+#include <float.h>
#include "index.h"
#include "card.h"
#include "split.h"
+#ifndef DBL_MAX
+#define DBL_MAX 1.797693E308 /* DBL_MAX approximation */
+#endif
+
struct Branch BranchBuf[MAXCARD + 1];
int BranchCount;
struct Rect CoverSplit;
@@ -37,18 +42,28 @@
static void RTreeGetBranches(struct Node *n, struct Branch *b,
struct RTree *t)
{
- int i, maxkids;
+ int i, maxkids = 0;
assert(n);
assert(b);
- maxkids = ((n)->level > 0 ? t->nodecard : t->leafcard);
+ if ((n)->level > 0) {
+ maxkids = t->nodecard;
+ /* load the branch buffer */
+ for (i = 0; i < maxkids; i++) {
+ assert(n->branch[i].child.ptr); /* n should have every entry full */
+ BranchBuf[i] = n->branch[i];
+ }
+ }
+ else {
+ maxkids = t->leafcard;
+ /* load the branch buffer */
+ for (i = 0; i < maxkids; i++) {
+ assert(n->branch[i].child.id); /* n should have every entry full */
+ BranchBuf[i] = n->branch[i];
+ }
+ }
- /* load the branch buffer */
- for (i = 0; i < maxkids; i++) {
- assert(n->branch[i].child); /* n should have every entry full */
- BranchBuf[i] = n->branch[i];
- }
BranchBuf[maxkids] = *b;
BranchCount = maxkids + 1;
@@ -59,7 +74,7 @@
}
CoverSplitArea = RTreeRectSphericalVolume(&CoverSplit, t);
- RTreeInitNode(n);
+ RTreeInitNode(n, n->level);
}
/*----------------------------------------------------------------------
@@ -463,6 +478,8 @@
maxkids = (minfill == t->min_leaf_fill ? t->leafcard : t->nodecard);
+ margin = DBL_MAX;
+
/* choose split axis */
/* For each dimension, sort rectangles first by lower boundary then
* by upper boundary. Get the smallest margin. */
@@ -471,8 +488,8 @@
best_cut[i] = 0;
best_side[i] = 0;
- smallest_overlap = -1;
- smallest_vol = -1;
+ smallest_overlap = DBL_MAX;
+ smallest_vol = DBL_MAX;
/* first lower then upper bounds for each axis */
for (s = 0; s < 2; s++) {
@@ -510,7 +527,7 @@
t) + RTreeRectMargin(&testrect2, t);
/* remember best axis */
- if (margin <= smallest_margin || first_time) {
+ if (margin <= smallest_margin) {
smallest_margin = margin;
best_axis = i;
first_time = 0;
@@ -552,7 +569,7 @@
t) + RTreeRectVolume(&testrect2, t);
/* get best cut for this axis */
- if (overlap <= smallest_overlap || smallest_overlap < 0) {
+ if (overlap <= smallest_overlap) {
smallest_overlap = overlap;
smallest_vol = vol;
best_cut[i] = j;
@@ -560,7 +577,7 @@
}
else if (overlap == smallest_overlap) {
/* resolve ties by minimum volume */
- if (vol <= smallest_vol || smallest_vol < 0) {
+ if (vol <= smallest_vol) {
smallest_vol = vol;
best_cut[i] = j;
best_side[i] = s;
More information about the grass-commit
mailing list