[GRASS-SVN] r51799 - grass/trunk/lib/vector/rtree
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat May 26 11:20:58 EDT 2012
Author: mmetz
Date: 2012-05-26 08:20:58 -0700 (Sat, 26 May 2012)
New Revision: 51799
Modified:
grass/trunk/lib/vector/rtree/index.c
grass/trunk/lib/vector/rtree/index.h
grass/trunk/lib/vector/rtree/indexf.c
grass/trunk/lib/vector/rtree/indexm.c
grass/trunk/lib/vector/rtree/io.c
grass/trunk/lib/vector/rtree/node.c
grass/trunk/lib/vector/rtree/rect.c
grass/trunk/lib/vector/rtree/rtree.h
grass/trunk/lib/vector/rtree/split.c
grass/trunk/lib/vector/rtree/split.h
Log:
n-dimensional rtree
Modified: grass/trunk/lib/vector/rtree/index.c
===================================================================
--- grass/trunk/lib/vector/rtree/index.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/index.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -22,7 +22,7 @@
#include <assert.h>
#include <grass/gis.h>
#include "index.h"
-#include "card.h"
+//#include "card.h"
/*
* Make a new index, empty.
@@ -35,9 +35,8 @@
{
struct RTree *new_rtree;
struct RTree_Node *n;
- int i;
+ int i, j;
- assert(ndims > 0);
new_rtree = (struct RTree *)malloc(sizeof(struct RTree));
new_rtree->fd = fd;
@@ -46,19 +45,24 @@
new_rtree->nsides = 2 * ndims;
/* hack to keep compatibility */
if (ndims < 3)
- new_rtree->nsides_alloc = 6;
+ new_rtree->ndims_alloc = 3;
else
- new_rtree->nsides_alloc = 2 * ndims;
-
- new_rtree->rectsize = sizeof(struct RTree_Rect);
+ new_rtree->ndims_alloc = ndims;
+ new_rtree->nsides_alloc = 2 * new_rtree->ndims_alloc;
+
/* init free nodes */
new_rtree->free_nodes.avail = 0;
new_rtree->free_nodes.alloc = 0;
new_rtree->free_nodes.pos = NULL;
- new_rtree->nodesize = sizeof(struct RTree_Node);
- new_rtree->branchsize = sizeof(struct RTree_Branch);
+ new_rtree->nodesize = sizeof(struct RTree_Node) -
+ MAXCARD * sizeof(RectReal *) +
+ MAXCARD * new_rtree->nsides_alloc * sizeof(RectReal);
+
+ new_rtree->branchsize = sizeof(struct RTree_Branch) -
+ sizeof(RectReal *) +
+ new_rtree->nsides_alloc * sizeof(RectReal);
/* create empty root node */
n = RTreeNewNode(new_rtree, 0);
@@ -82,6 +86,15 @@
new_rtree->used[i][0] = 2;
new_rtree->used[i][1] = 1;
new_rtree->used[i][2] = 0;
+
+ /* alloc memory for rectangles */
+ for (j = 0; j < MAXCARD; j++) {
+ RTreeNewRect(&(new_rtree->nb[i][0].n.branch[j].rect), new_rtree);
+ RTreeNewRect(&(new_rtree->nb[i][1].n.branch[j].rect), new_rtree);
+ RTreeNewRect(&(new_rtree->nb[i][2].n.branch[j].rect), new_rtree);
+
+ RTreeNewRect(&(new_rtree->fs[i].sn.branch[j].rect), new_rtree);
+ }
}
/* write empty root node */
@@ -97,7 +110,6 @@
new_rtree->delete_rect = RTreeDeleteRectF;
new_rtree->search_rect = RTreeSearchF;
new_rtree->valid_child = RTreeValidChildF;
-
}
else { /* memory based */
new_rtree->nodecard = MAXCARD;
@@ -123,11 +135,29 @@
new_rtree->n_nodes = 1;
new_rtree->n_leafs = 0;
+ /* initialize temp variables */
+ RTreeNewRect(&(new_rtree->p.cover[0]), new_rtree);
+ RTreeNewRect(&(new_rtree->p.cover[1]), new_rtree);
+
+ RTreeNewRect(&(new_rtree->tmpb1.rect), new_rtree);
+ RTreeNewRect(&(new_rtree->tmpb2.rect), new_rtree);
+ RTreeNewRect(&(new_rtree->c.rect), new_rtree);
+ for (i = 0; i <= MAXCARD; i++) {
+ RTreeNewRect(&(new_rtree->BranchBuf[i].rect), new_rtree);
+ }
+ RTreeNewRect(&(new_rtree->rect_0), new_rtree);
+ RTreeNewRect(&(new_rtree->rect_1), new_rtree);
+ RTreeNewRect(&(new_rtree->upperrect), new_rtree);
+ RTreeNewRect(&(new_rtree->orect), new_rtree);
+ new_rtree->center_n = (RectReal *)malloc(new_rtree->ndims_alloc * sizeof(RectReal));
+
return new_rtree;
}
void RTreeFreeIndex(struct RTree *t)
{
+ int i, j;
+
assert(t);
if (t->fd > -1) {
@@ -137,6 +167,37 @@
else if (t->root)
RTreeDestroyNode(t->root, t->root->level ? t->nodecard : t->leafcard);
+ if (t->fd > -1) { /* file based */
+ /* free node buffer */
+ for (i = 0; i < MAXLEVEL; i++) {
+
+ /* free memory for rectangles */
+ for (j = 0; j < MAXCARD; j++) {
+ free(t->nb[i][0].n.branch[j].rect.boundary);
+ free(t->nb[i][1].n.branch[j].rect.boundary);
+ free(t->nb[i][2].n.branch[j].rect.boundary);
+
+ free(t->fs[i].sn.branch[j].rect.boundary);
+ }
+ }
+ }
+
+ /* free temp variables */
+ free(t->p.cover[0].boundary);
+ free(t->p.cover[1].boundary);
+
+ free(t->tmpb1.rect.boundary);
+ free(t->tmpb2.rect.boundary);
+ free(t->c.rect.boundary);
+ for (i = 0; i <= MAXCARD; i++) {
+ free(t->BranchBuf[i].rect.boundary);
+ }
+ free(t->rect_0.boundary);
+ free(t->rect_1.boundary);
+ free(t->upperrect.boundary);
+ free(t->orect.boundary);
+ free(t->center_n);
+
free(t);
return;
@@ -144,7 +205,7 @@
/*
* Search in an index tree for all data retangles that
- * overlap the argument rectangle.
+ * overlap or touch the argument rectangle.
* Return the number of qualifying data rects.
*/
int RTreeSearch(struct RTree *t, struct RTree_Rect *r, SearchHitCallback *shcb,
@@ -228,6 +289,7 @@
*/
void RTreeFreeListBranch(struct RTree_ListBranch *p)
{
+ free(p->b.rect.boundary);
free(p);
}
Modified: grass/trunk/lib/vector/rtree/index.h
===================================================================
--- grass/trunk/lib/vector/rtree/index.h 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/index.h 2012-05-26 15:20:58 UTC (rev 51799)
@@ -50,6 +50,8 @@
int level;
};
+/* functions */
+
/* index.c */
struct RTree_ListNode *RTreeNewListNode(void);
void RTreeFreeListNode(struct RTree_ListNode *);
@@ -68,29 +70,37 @@
void *);
int RTreeInsertRectF(struct RTree_Rect *, union RTree_Child, int, struct RTree *);
int RTreeDeleteRectF(struct RTree_Rect *, union RTree_Child, struct RTree *);
-int RTreeValidChildF(union RTree_Child *child);
+int RTreeValidChildF(union RTree_Child *);
/* node.c */
-struct RTree_Rect RTreeNodeCover(struct RTree_Node *, struct RTree *);
+void RTreeNodeCover(struct RTree_Node *, struct RTree_Rect *, struct RTree *);
int RTreeAddBranch(struct RTree_Branch *, struct RTree_Node *, struct RTree_Node **,
struct RTree_ListBranch **, struct RTree_Rect *, int *, struct RTree *);
int RTreePickBranch(struct RTree_Rect *, struct RTree_Node *, struct RTree *);
void RTreeDisconnectBranch(struct RTree_Node *, int, struct RTree *);
void RTreePrintNode(struct RTree_Node *, int, struct RTree *);
void RTreeTabIn(int);
+void RTreeCopyNode(struct RTree_Node *, struct RTree_Node *, struct RTree *);
+void RTreeCopyBranch(struct RTree_Branch *, struct RTree_Branch *, struct RTree *);
/* rect.c */
-void RTreeNewRect(struct RTree_Rect *, struct RTree *);
void RTreeInitRect(struct RTree_Rect *, struct RTree *);
-struct RTree_Rect RTreeNullRect(void);
+void RTreeNullRect(struct RTree_Rect *, struct RTree *);
RectReal RTreeRectArea(struct RTree_Rect *, struct RTree *);
RectReal RTreeRectSphericalVolume(struct RTree_Rect *, struct RTree *);
RectReal RTreeRectVolume(struct RTree_Rect *, struct RTree *);
RectReal RTreeRectMargin(struct RTree_Rect *, struct RTree *);
-struct RTree_Rect RTreeCombineRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *);
+void RTreeCombineRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree_Rect *, struct RTree *);
+void RTreeExpandRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *);
int RTreeCompareRect(struct RTree_Rect *, struct RTree_Rect *, struct RTree *);
-void RTreePrintRect(struct RTree_Rect *, int);
+void RTreePrintRect(struct RTree_Rect *, int, struct RTree *);
+/*-----------------------------------------------------------------------------
+| Copy second rectangle to first rectangle.
+-----------------------------------------------------------------------------*/
+#define RTreeCopyRect(r1, r2, t) memcpy((r1)->boundary, (r2)->boundary, (t)->nsides_alloc * sizeof(RectReal))
+
+
/* split.c */
void RTreeSplitNode(struct RTree_Node *, struct RTree_Branch *, struct RTree_Node *, struct RTree *);
Modified: grass/trunk/lib/vector/rtree/indexf.c
===================================================================
--- grass/trunk/lib/vector/rtree/indexf.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/indexf.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -24,16 +24,8 @@
#include <grass/config.h>
#include <grass/gis.h>
#include "index.h"
-#include "card.h"
+//#include "card.h"
-/* stack used for non-recursive insertion/deletion */
-struct fstack
-{
- struct RTree_Node sn; /* stack node */
- int branch_id; /* branch no to follow down */
- off_t pos; /* file position of stack node */
-};
-
int RTreeValidChildF(union RTree_Child *child)
{
return (child->pos > -1);
@@ -50,8 +42,8 @@
struct RTree_Node *n;
int hitCount = 0, found, currlevel;
int i;
- struct fstack s[MAXLEVEL];
int top = 0;
+ struct fstack *s = t->fs;
/* stack size of t->rootlevel + 1 is enough because of depth first search */
/* only one node per level on stack at any given time */
@@ -121,13 +113,25 @@
struct RTree_ListBranch **ee, int *overflow)
{
int i, currlevel;
- struct RTree_Branch b;
- struct RTree_Rect nr, *cover;
- struct RTree_Node *n, *n2, nn;
- struct fstack s[MAXLEVEL];
+ struct RTree_Rect *cover;
+ struct RTree_Node *n, *n2;
int top = 0, down = 0;
+ struct RTree_Branch *b = &(t->tmpb2);
int result;
+ struct fstack *s = t->fs;
+ static struct RTree_Node nn;
+ static struct RTree_Rect nr;
+ static int rect_init = 0;
+
+ if (!rect_init) {
+ for (i = 0; i < MAXCARD; i++) {
+ RTreeNewRect(&(nn.branch[i].rect), t);
+ }
+ RTreeNewRect(&nr, t);
+ rect_init = t->ndims_alloc;
+ }
+
n2 = &nn;
/* add root node position to stack */
@@ -149,15 +153,15 @@
/* Have reached level for insertion. Add rect, split if necessary */
if (s[top].sn.level == level) {
- b.rect = *r;
+ RTreeCopyRect(&(b->rect), r, t);
/* child field of leaves contains tid of data record */
- b.child = child;
+ b->child = child;
/* add branch, may split node or remove branches */
if (top)
cover = &(s[top - 1].sn.branch[s[top - 1].branch_id].rect);
else
cover = NULL;
- result = RTreeAddBranch(&b, &(s[top].sn), &n2, ee, cover, overflow, t);
+ result = RTreeAddBranch(b, &(s[top].sn), &n2, ee, cover, overflow, t);
/* write out new node if node was split */
if (result == 1) {
*newnode_pos = RTreeGetNodePos(t);
@@ -178,7 +182,7 @@
down = top--;
i = s[top].branch_id;
if (result == 0) { /* branch was added */
- nr = RTreeCombineRect(r, &(s[top].sn.branch[i].rect), t);
+ RTreeCombineRect(&(s[top].sn.branch[i].rect), &nr, r, t);
/* rewrite rect */
if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
@@ -186,7 +190,7 @@
}
else if (result == 2) { /* branches were removed */
/* get node cover of previous node */
- nr = RTreeNodeCover(&(s[down].sn), t);
+ RTreeNodeCover(&(s[down].sn), &nr, t);
/* rewrite rect */
if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
@@ -194,17 +198,17 @@
}
else if (result == 1) { /* node was split */
/* get node cover of previous node */
- s[top].sn.branch[i].rect = RTreeNodeCover(&(s[down].sn), t);
+ RTreeNodeCover(&(s[down].sn), &(s[top].sn.branch[i].rect), t);
/* add new branch for new node previously added by RTreeAddBranch() */
- b.child.pos = *newnode_pos;
- b.rect = RTreeNodeCover(n2, t);
+ b->child.pos = *newnode_pos;
+ RTreeNodeCover(n2, &(b->rect), t);
/* add branch, may split node or remove branches */
if (top)
cover = &(s[top - 1].sn.branch[s[top - 1].branch_id].rect);
else
cover = NULL;
- result = RTreeAddBranch(&b, &(s[top].sn), &n2, ee, cover, overflow, t);
+ result = RTreeAddBranch(b, &(s[top].sn), &n2, ee, cover, overflow, t);
/* write out new node if node was split */
if (result == 1) {
@@ -217,7 +221,8 @@
}
}
- *newnode = *n2;
+ /* copy node */
+ RTreeCopyNode(newnode, n2, t);
return result;
}
@@ -233,13 +238,24 @@
int RTreeInsertRectF(struct RTree_Rect *r, union RTree_Child child, int level,
struct RTree *t)
{
- struct RTree_Node oldroot, newroot, newnode;
- struct RTree_Branch b;
struct RTree_ListBranch *e, *reInsertList = NULL;
int result;
int i, overflow[MAXLEVEL];
off_t newnode_pos = -1;
+ static struct RTree_Node oldroot, newroot, newnode;
+ struct RTree_Branch *b = &(t->tmpb1);
+ static int rect_init = 0;
+
+ if (!rect_init) {
+ for (i = 0; i < MAXCARD; i++) {
+ RTreeNewRect(&(oldroot.branch[i].rect), t);
+ RTreeNewRect(&(newroot.branch[i].rect), t);
+ RTreeNewRect(&(newnode.branch[i].rect), t);
+ }
+ rect_init = t->ndims_alloc;
+ }
+
/* R*-tree forced reinsertion: for each level only once */
for (i = 0; i < MAXLEVEL; i++)
overflow[i] = 1;
@@ -255,13 +271,13 @@
RTreeInitNode(t, &newroot, NODETYPE(t->rootlevel, t->fd));
newroot.level = t->rootlevel;
/* branch for old root */
- b.rect = RTreeNodeCover(&oldroot, t);
- b.child.pos = t->rootpos;
- RTreeAddBranch(&b, &newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(&oldroot, &(b->rect), t);
+ b->child.pos = t->rootpos;
+ RTreeAddBranch(b, &newroot, NULL, NULL, NULL, NULL, t);
/* branch for new node created by RTreeInsertRect2F() */
- b.rect = RTreeNodeCover(&newnode, t);
- b.child.pos = newnode_pos; /* offset to new node as returned by RTreeInsertRect2F() */
- RTreeAddBranch(&b, &newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(&newnode, &(b->rect), t);
+ b->child.pos = newnode_pos; /* offset to new node as returned by RTreeInsertRect2F() */
+ RTreeAddBranch(b, &newroot, NULL, NULL, NULL, NULL, t);
/* write new root node */
t->rootpos = RTreeGetNodePos(t);
RTreeWriteNode(&newroot, t);
@@ -270,14 +286,14 @@
else if (result == 2) { /* branches were removed */
while (reInsertList) {
/* get next branch in list */
- b = reInsertList->b;
+ RTreeCopyBranch(b, &(reInsertList->b), t);
level = reInsertList->level;
e = reInsertList;
reInsertList = reInsertList->next;
RTreeFreeListBranch(e);
/* reinsert branches */
result =
- RTreeInsertRect2F(&(b.rect), b.child, level, &newnode, &newnode_pos, t,
+ RTreeInsertRect2F(&(b->rect), b->child, level, &newnode, &newnode_pos, t,
&reInsertList, overflow);
if (result == 1) { /* root split */
@@ -287,13 +303,13 @@
RTreeInitNode(t, &newroot, NODETYPE(t->rootlevel, t->fd));
newroot.level = t->rootlevel;
/* branch for old root */
- b.rect = RTreeNodeCover(&oldroot, t);
- b.child.pos = t->rootpos;
- RTreeAddBranch(&b, &newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(&oldroot, &(b->rect), t);
+ b->child.pos = t->rootpos;
+ RTreeAddBranch(b, &newroot, NULL, NULL, NULL, NULL, t);
/* branch for new node created by RTreeInsertRect2F() */
- b.rect = RTreeNodeCover(&newnode, t);
- b.child.pos = newnode_pos;
- RTreeAddBranch(&b, &newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(&newnode, &(b->rect), t);
+ b->child.pos = newnode_pos;
+ RTreeAddBranch(b, &newroot, NULL, NULL, NULL, NULL, t);
/* write new root node */
t->rootpos = RTreeGetNodePos(t);
RTreeWriteNode(&newroot, t);
@@ -317,13 +333,20 @@
{
int i, notfound = 1, currlevel;
struct RTree_Node *n;
- struct RTree_Rect nr;
- struct fstack s[MAXLEVEL];
int top = 0, down = 0;
int minfill;
+ struct fstack *s = t->fs;
+ static struct RTree_Rect nr;
+ static int rect_init = 0;
+
assert(ee);
+ if (!rect_init) {
+ RTreeNewRect(&(nr), t);
+ rect_init = 1;
+ }
+
/* add root node position to stack */
currlevel = t->rootlevel;
s[top].pos = t->rootpos;
@@ -384,7 +407,7 @@
minfill = (s[down].sn.level ? t->min_node_fill : t->min_leaf_fill);
if (s[down].sn.count >= minfill) {
/* just update node cover */
- nr = RTreeNodeCover(&(s[down].sn), t);
+ RTreeNodeCover(&(s[down].sn), &nr, t);
/* rewrite rect */
if (!RTreeCompareRect(&nr, &(s[top].sn.branch[i].rect), t)) {
RTreeUpdateRect(&nr, &(s[top].sn), s[top].pos, i, t);
@@ -394,7 +417,8 @@
/* not enough entries in child, eliminate child node */
assert(s[top].sn.branch[i].child.pos == s[down].pos);
n = RTreeNewNode(t, s[down].sn.level);
- memcpy(n, &(s[down].sn), t->nodesize);
+ /* copy node */
+ RTreeCopyNode(n, &(s[down].sn), t);
RTreeAddNodePos(s[top].sn.branch[i].child.pos, s[down].sn.level, t);
RTreeReInsertNode(n, ee);
RTreeDisconnectBranch(&(s[top].sn), i, t);
@@ -417,9 +441,19 @@
int RTreeDeleteRectF(struct RTree_Rect *r, union RTree_Child child, struct RTree *t)
{
int i;
- struct RTree_Node *n, rn;
+ struct RTree_Node *n;
struct RTree_ListNode *e, *reInsertList = NULL;
+ static struct RTree_Node rn;
+ static int rect_init = 0;
+
+ if (!rect_init) {
+ for (i = 0; i < MAXCARD; i++) {
+ RTreeNewRect(&(rn.branch[i].rect), t);
+ }
+ rect_init = 1;
+ }
+
if (!RTreeDeleteRect2F(r, child, t, &reInsertList)) {
/* found and deleted a data item */
Modified: grass/trunk/lib/vector/rtree/indexm.c
===================================================================
--- grass/trunk/lib/vector/rtree/indexm.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/indexm.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -20,15 +20,8 @@
#include <assert.h>
#include <grass/gis.h>
#include "index.h"
-#include "card.h"
+//#include "card.h"
-/* stack used for non-recursive insertion/deletion */
-struct stack
-{
- struct RTree_Node *sn; /* stack node */
- int branch_id; /* branch no to follow down */
-};
-
int RTreeValidChildM(union RTree_Child *child)
{
return (child->ptr != NULL);
@@ -45,8 +38,8 @@
struct RTree_Node *n;
int hitCount = 0, found;
int i;
- struct stack s[MAXLEVEL];
int top = 0;
+ struct mstack *s = t->ms;
/* stack size of t->rootlevel + 1 is enough because of depth first search */
/* only one node per level on stack at any given time */
@@ -113,12 +106,12 @@
struct RTree_ListBranch **ee, int *overflow)
{
int i;
- struct RTree_Branch b;
struct RTree_Node *n, *n2;
struct RTree_Rect *cover;
- struct stack s[MAXLEVEL];
int top = 0, down = 0;
int result;
+ struct RTree_Branch *b = &(t->tmpb2);
+ struct mstack *s = t->ms;
/* add root node to stack */
s[top].sn = t->root;
@@ -134,15 +127,15 @@
/* Have reached level for insertion. Remove p rectangles or split */
if (s[top].sn->level == level) {
- b.rect = *r;
+ RTreeCopyRect(&(b->rect), r, t);
/* child field of leaves contains tid of data record */
- b.child = child;
+ b->child = child;
/* add branch, may split node or remove branches */
if (top)
cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect);
else
cover = NULL;
- result = RTreeAddBranch(&b, s[top].sn, &n2, ee, cover, overflow, t);
+ result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
/* update node count */
if (result == 1) {
t->n_nodes++;
@@ -159,19 +152,18 @@
down = top--;
i = s[top].branch_id;
if (result == 0) { /* branch was added */
- s[top].sn->branch[i].rect =
- RTreeCombineRect(r, &(s[top].sn->branch[i].rect), t);
+ RTreeExpandRect(&(s[top].sn->branch[i].rect), r, t);
}
else if (result == 2) { /* branches were removed */
/* get node cover of previous node */
- s[top].sn->branch[i].rect = RTreeNodeCover(s[down].sn, t);
+ RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
}
else if (result == 1) { /* node was split */
/* get node cover of previous node */
- s[top].sn->branch[i].rect = RTreeNodeCover(s[down].sn, t);
+ RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
/* add new branch for new node previously added by RTreeAddBranch() */
- b.child.ptr = n2;
- b.rect = RTreeNodeCover(b.child.ptr, t);
+ b->child.ptr = n2;
+ RTreeNodeCover(b->child.ptr, &(b->rect), t);
/* add branch, may split node or remove branches */
if (top)
@@ -179,7 +171,7 @@
else
cover = NULL;
result =
- RTreeAddBranch(&b, s[top].sn, &n2, ee, cover, overflow, t);
+ RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t);
/* update node count */
if (result == 1) {
@@ -205,11 +197,11 @@
struct RTree *t)
{
struct RTree_Node *newnode, *newroot;
- struct RTree_Branch b;
struct RTree_ListBranch *reInsertList = NULL;
struct RTree_ListBranch *e;
int result;
int i, overflow[MAXLEVEL];
+ struct RTree_Branch *b = &(t->tmpb1);
/* R*-tree forced reinsertion: for each level only once */
for (i = 0; i < MAXLEVEL; i++)
@@ -225,13 +217,13 @@
newroot = RTreeNewNode(t, t->rootlevel);
newroot->level = t->rootlevel;
/* branch for old root */
- b.rect = RTreeNodeCover(t->root, t);
- b.child.ptr = t->root;
- RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(t->root, &(b->rect), t);
+ 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.ptr = newnode;
- RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(newnode, &(b->rect), t);
+ b->child.ptr = newnode;
+ RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
/* set new root node */
t->root = newroot;
t->n_nodes++;
@@ -239,14 +231,14 @@
else if (result == 2) { /* branches were removed */
while (reInsertList) {
/* get next branch in list */
- b = reInsertList->b;
+ RTreeCopyBranch(b, &(reInsertList->b), t);
level = reInsertList->level;
e = reInsertList;
reInsertList = reInsertList->next;
RTreeFreeListBranch(e);
/* reinsert branches */
result =
- RTreeInsertRect2M(&(b.rect), b.child, level, &newnode, t,
+ RTreeInsertRect2M(&(b->rect), b->child, level, &newnode, t,
&reInsertList, overflow);
if (result == 1) { /* root split */
@@ -255,13 +247,13 @@
newroot = RTreeNewNode(t, t->rootlevel);
newroot->level = t->rootlevel;
/* branch for old root */
- b.rect = RTreeNodeCover(t->root, t);
- b.child.ptr = t->root;
- RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(t->root, &(b->rect), t);
+ 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.ptr = newnode;
- RTreeAddBranch(&b, newroot, NULL, NULL, NULL, NULL, t);
+ RTreeNodeCover(newnode, &(b->rect), t);
+ b->child.ptr = newnode;
+ RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
/* set new root node */
t->root = newroot;
t->n_nodes++;
@@ -284,9 +276,9 @@
{
int i, notfound = 1;
struct RTree_Node *n;
- struct stack s[MAXLEVEL];
int top = 0, down = 0;
int minfill;
+ struct mstack *s = t->ms;
assert(ee);
@@ -348,7 +340,7 @@
minfill = (s[down].sn->level ? t->min_node_fill : t->min_leaf_fill);
if (s[down].sn->count >= minfill) {
/* just update node cover */
- s[top].sn->branch[i].rect = RTreeNodeCover(s[down].sn, t);
+ RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t);
}
else {
/* not enough entries in child, eliminate child node */
Modified: grass/trunk/lib/vector/rtree/io.c
===================================================================
--- grass/trunk/lib/vector/rtree/io.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/io.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -67,11 +67,32 @@
}
}
+/* read branch from file */
+size_t RTreeReadBranch(struct RTree_Branch *b, struct RTree *t)
+{
+ size_t size = 0;
+
+ size += read(t->fd, b->rect.boundary, t->nsides * sizeof(RectReal));
+ size += read(t->fd, &(b->child), sizeof(union RTree_Child));
+
+ return size;
+}
+
/* read node from file */
size_t RTreeReadNode(struct RTree_Node *n, off_t nodepos, struct RTree *t)
{
+ int i;
+ size_t size = 0;
+
lseek(t->fd, nodepos, SEEK_SET);
- return read(t->fd, n, t->nodesize);
+ size += read(t->fd, &(n->count), sizeof(int));
+ size += read(t->fd, &(n->level), sizeof(int));
+
+ for (i = 0; i < MAXCARD; i++) {
+ size += RTreeReadBranch(&(n->branch[i]), t);
+ }
+
+ return size;
}
/* get node from buffer or file */
@@ -100,14 +121,36 @@
t->used[level][1] = t->used[level][0];
t->used[level][0] = which;
}
- *n = t->nb[level][which].n;
+ /* copy node */
+ RTreeCopyNode(n, &(t->nb[level][which].n), t);
}
+/* write branch to file */
+size_t RTreeWriteBranch(struct RTree_Branch *b, struct RTree *t)
+{
+ size_t size = 0;
+
+ size += write(t->fd, b->rect.boundary, t->nsides * sizeof(RectReal));
+ size += write(t->fd, &(b->child), sizeof(union RTree_Child));
+
+ return size;
+}
+
/* write new node to file */
size_t RTreeWriteNode(struct RTree_Node *n, struct RTree *t)
{
+ int i;
+ size_t size = 0;
+
/* file position must be set first with RTreeGetFNodePos() */
- return write(t->fd, n, t->nodesize);
+ size += write(t->fd, &(n->count), sizeof(int));
+ size += write(t->fd, &(n->level), sizeof(int));
+
+ for (i = 0; i < MAXCARD; i++) {
+ size += RTreeWriteBranch(&(n->branch[i]), t);
+ }
+
+ return size;
}
/* rewrite updated node to file */
@@ -122,7 +165,8 @@
{
int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
- t->nb[n->level][which].n = *n;
+ /* copy node */
+ RTreeCopyNode(&(t->nb[n->level][which].n), n, t);
t->nb[n->level][which].dirty = 1;
/* make it mru */
@@ -140,9 +184,15 @@
/* update rectangle */
void RTreeUpdateRect(struct RTree_Rect *r, struct RTree_Node *n, off_t nodepos, int b, struct RTree *t)
{
- int which = (nodepos == t->nb[n->level][2].pos ? 2 : nodepos == t->nb[n->level][1].pos);
+ int i;
+ int which = (nodepos == t->nb[n->level][2].pos ?
+ 2 : nodepos == t->nb[n->level][1].pos);
- t->nb[n->level][which].n.branch[b].rect = n->branch[b].rect = *r;
+ for (i = 0; i < t->nsides; i++) {
+ t->nb[n->level][which].n.branch[b].rect.boundary[i] =
+ n->branch[b].rect.boundary[i] = r->boundary[i];
+ }
+
t->nb[n->level][which].dirty = 1;
/* make it mru */
Modified: grass/trunk/lib/vector/rtree/node.c
===================================================================
--- grass/trunk/lib/vector/rtree/node.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/node.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -18,9 +18,11 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <assert.h>
#include <grass/gis.h>
#include "index.h"
+#include "split.h"
#include "card.h"
/* rectangle distances for forced removal */
@@ -31,27 +33,27 @@
};
/* Initialize one branch cell in an internal node. */
-static void RTreeInitNodeBranchM(struct RTree *t, struct RTree_Branch *b)
+static void RTreeInitNodeBranchM(struct RTree_Branch *b, struct RTree *t)
{
RTreeInitRect(&(b->rect), t);
b->child.ptr = NULL;
}
/* Initialize one branch cell in an internal node. */
-static void RTreeInitNodeBranchF(struct RTree *t, struct RTree_Branch *b)
+static void RTreeInitNodeBranchF(struct RTree_Branch *b, struct RTree *t)
{
RTreeInitRect(&(b->rect), t);
b->child.pos = -1;
}
/* Initialize one branch cell in a leaf node. */
-static void RTreeInitLeafBranch(struct RTree *t, struct RTree_Branch *b)
+static void RTreeInitLeafBranch(struct RTree_Branch *b, struct RTree *t)
{
RTreeInitRect(&(b->rect), t);
b->child.id = 0;
}
-static void (*RTreeInitBranch[3]) () = {
+static void (*RTreeInitBranch[3]) (struct RTree_Branch *b, struct RTree *t) = {
RTreeInitLeafBranch, RTreeInitNodeBranchM, RTreeInitNodeBranchF
};
@@ -65,45 +67,79 @@
n->level = -1;
for (i = 0; i < MAXCARD; i++)
- RTreeInitBranch[type](t, &(n->branch[i]));
+ RTreeInitBranch[type](&(n->branch[i]), t);
}
/* Make a new node and initialize to have all branch cells empty. */
struct RTree_Node *RTreeNewNode(struct RTree *t, int level)
{
+ int i;
struct RTree_Node *n;
- n = (struct RTree_Node *)malloc((size_t) t->nodesize);
+ n = (struct RTree_Node *)malloc(sizeof(struct RTree_Node));
assert(n);
- RTreeInitNode(t, n, NODETYPE(level, t->fd));
+
+ n->count = 0;
+ n->level = -1;
+
+ for (i = 0; i < MAXCARD; i++) {
+ RTreeNewRect(&(n->branch[i].rect), t);
+ RTreeInitBranch[NODETYPE(level, t->fd)](&(n->branch[i]), t);
+ }
+
return n;
}
void RTreeFreeNode(struct RTree_Node *n)
{
+ int i;
+
assert(n);
+
+ for (i = 0; i < MAXCARD; i++)
+ free(n->branch[i].rect.boundary);
+
free(n);
}
+/* copy node 2 to node 1 */
+void RTreeCopyNode(struct RTree_Node *n1, struct RTree_Node *n2, struct RTree *t)
+{
+ int i;
+
+ assert(n1 && n2);
+
+ n1->count = n2->count;
+ n1->level = n2->level;
+ for (i = 0; i < MAXCARD; i++) {
+ RTreeCopyBranch(&(n1->branch[i]), &(n2->branch[i]), t);
+ }
+}
+
+/* copy branch 2 to branch 1 */
+void RTreeCopyBranch(struct RTree_Branch *b1, struct RTree_Branch *b2, struct RTree *t)
+{
+ b1->child = b2->child;
+ RTreeCopyRect(&(b1->rect), &(b2->rect), t);
+}
+
/*
* Find the smallest rectangle that includes all rectangles in
* branches of a node.
*/
-struct RTree_Rect RTreeNodeCover(struct RTree_Node *n, struct RTree *t)
+void RTreeNodeCover(struct RTree_Node *n, struct RTree_Rect *r, struct RTree *t)
{
int i, first_time = 1;
- struct RTree_Rect r;
- RTreeInitRect(&r, t);
if ((n)->level > 0) { /* internal node */
for (i = 0; i < t->nodecard; i++) {
if (t->valid_child(&(n->branch[i].child))) {
if (first_time) {
- r = n->branch[i].rect;
+ RTreeCopyRect(r, &(n->branch[i].rect), t);
first_time = 0;
}
else
- r = RTreeCombineRect(&r, &(n->branch[i].rect), t);
+ RTreeExpandRect(r, &(n->branch[i].rect), t);
}
}
}
@@ -111,15 +147,14 @@
for (i = 0; i < t->leafcard; i++) {
if (n->branch[i].child.id) {
if (first_time) {
- r = n->branch[i].rect;
+ RTreeCopyRect(r, &(n->branch[i].rect), t);
first_time = 0;
}
else
- r = RTreeCombineRect(&r, &(n->branch[i].rect), t);
+ RTreeExpandRect(r, &(n->branch[i].rect), t);
}
}
}
- return r;
}
/*
@@ -140,7 +175,6 @@
int i, j;
RectReal increase, bestIncr = -1, area, bestArea = 0;
int best = 0, bestoverlap;
- struct RTree_Rect tmp_rect;
int overlap;
bestoverlap = t->nodecard + 1;
@@ -150,15 +184,15 @@
for (i = 0; i < t->nodecard; i++) {
if (t->valid_child(&(n->branch[i].child))) {
rr = &n->branch[i].rect;
- tmp_rect = RTreeCombineRect(r, rr, t);
+ RTreeCombineRect(r, rr, &(t->orect), t);
area = RTreeRectSphericalVolume(rr, t);
- increase = RTreeRectSphericalVolume(&tmp_rect, t) - area;
+ increase = RTreeRectSphericalVolume(&(t->orect), t) - area;
overlap = 0;
for (j = 0; j < t->leafcard; j++) {
if (j != i) {
rr = &n->branch[j].rect;
- overlap += RTreeOverlap(&tmp_rect, rr, t);
+ overlap += RTreeOverlap(&(t->orect), rr, t);
}
}
@@ -199,7 +233,6 @@
int i, first_time = 1;
RectReal increase, bestIncr = (RectReal) -1, area, bestArea = 0;
int best = 0;
- struct RTree_Rect tmp_rect;
assert((n)->level > 0); /* must not be called on leaf node */
@@ -210,8 +243,8 @@
if (t->valid_child(&(n->branch[i].child))) {
rr = &n->branch[i].rect;
area = RTreeRectSphericalVolume(rr, t);
- tmp_rect = RTreeCombineRect(r, rr, t);
- increase = RTreeRectSphericalVolume(&tmp_rect, t) - area;
+ RTreeCombineRect(r, rr, &(t->orect), t);
+ increase = RTreeRectSphericalVolume(&(t->orect), t) - area;
if (increase < bestIncr || first_time) {
best = i;
bestArea = area;
@@ -234,14 +267,14 @@
assert(n && i >= 0 && i < t->nodecard);
assert(t->valid_child(&(n->branch[i].child)));
if (t->fd < 0)
- RTreeInitNodeBranchM(t, &(n->branch[i]));
+ RTreeInitNodeBranchM(&(n->branch[i]), t);
else
- RTreeInitNodeBranchF(t, &(n->branch[i]));
+ RTreeInitNodeBranchF(&(n->branch[i]), t);
}
else {
assert(n && i >= 0 && i < t->leafcard);
assert(n->branch[i].child.id);
- RTreeInitLeafBranch(t, &(n->branch[i]));
+ RTreeInitLeafBranch(&(n->branch[i]), t);
}
n->count--;
@@ -398,9 +431,15 @@
* Allocate space for a branch in the list used in InsertRect to
* store branches of nodes that are too full.
*/
-static struct RTree_ListBranch *RTreeNewListBranch(void)
+static struct RTree_ListBranch *RTreeNewListBranch(struct RTree *t)
{
- return (struct RTree_ListBranch *)malloc(sizeof(struct RTree_ListBranch));
+ struct RTree_ListBranch *p =
+ (struct RTree_ListBranch *)malloc(sizeof(struct RTree_ListBranch));
+
+ assert(p);
+ RTreeNewRect(&(p->b.rect), t);
+
+ return p;
}
/*
@@ -408,12 +447,12 @@
* be reinserted into the index structure.
*/
static void RTreeReInsertBranch(struct RTree_Branch b, int level,
- struct RTree_ListBranch **ee)
+ struct RTree_ListBranch **ee, struct RTree *t)
{
register struct RTree_ListBranch *l;
- l = RTreeNewListBranch();
- l->b = b;
+ l = RTreeNewListBranch(t);
+ RTreeCopyBranch(&(l->b), &b, t);
l->level = level;
l->next = *ee;
*ee = l;
@@ -429,11 +468,12 @@
struct RTree *t)
{
int i, j, maxkids, type;
- RectReal center_n[NUMDIMS], center_r, delta;
- struct RTree_Branch branchbuf[MAXCARD + 1];
+ RectReal center_r, delta;
struct dist rdist[MAXCARD + 1];
- struct RTree_Rect new_cover;
+ struct RTree_Rect *new_cover = &(t->orect);
+ RectReal *center_n = t->center_n;
+
assert(cover);
maxkids = MAXKIDS((n)->level, t);
@@ -441,35 +481,35 @@
assert(n->count == maxkids); /* must be full */
- new_cover = RTreeCombineRect(cover, &(b->rect), t);
+ RTreeCombineRect(cover, &(b->rect), new_cover, t);
/* center coords of node cover */
for (j = 0; j < t->ndims; j++) {
- center_n[j] = (new_cover.boundary[j + NUMDIMS] + new_cover.boundary[j]) / 2;
+ center_n[j] = (new_cover->boundary[j + t->ndims_alloc] + new_cover->boundary[j]) / 2;
}
/* compute distances of child rectangle centers to node cover center */
for (i = 0; i < maxkids; i++) {
- branchbuf[i] = n->branch[i];
+ RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
rdist[i].distance = 0;
rdist[i].id = i;
for (j = 0; j < t->ndims; j++) {
center_r =
- (branchbuf[i].rect.boundary[j + NUMDIMS] +
- branchbuf[i].rect.boundary[j]) / 2;
+ (t->BranchBuf[i].rect.boundary[j + t->ndims_alloc] +
+ t->BranchBuf[i].rect.boundary[j]) / 2;
delta = center_n[j] - center_r;
rdist[i].distance += delta * delta;
}
- RTreeInitBranch[type](t, &(n->branch[i]));
+ RTreeInitBranch[type](&(n->branch[i]), t);
}
/* new branch */
- branchbuf[maxkids] = *b;
+ RTreeCopyBranch(&(t->BranchBuf[maxkids]), b, t);
rdist[maxkids].distance = 0;
for (j = 0; j < t->ndims; j++) {
center_r =
- (b->rect.boundary[j + NUMDIMS] +
+ (b->rect.boundary[j + t->ndims_alloc] +
b->rect.boundary[j]) / 2;
delta = center_n[j] - center_r;
rdist[maxkids].distance += delta * delta;
@@ -481,11 +521,11 @@
/* 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);
+ RTreeReInsertBranch(t->BranchBuf[rdist[maxkids - i].id], n->level, ee, t);
}
/* put remaining in node, closest to center first */
for (i = 0; i < maxkids - FORCECARD + 1; i++) {
- n->branch[i] = branchbuf[rdist[i].id];
+ RTreeCopyBranch(&(n->branch[i]), &(t->BranchBuf[rdist[i].id]), t);
}
n->count = maxkids - FORCECARD + 1;
}
@@ -509,7 +549,9 @@
if ((n)->level > 0) { /* internal node */
for (i = 0; i < maxkids; i++) { /* find empty branch */
if (!t->valid_child(&(n->branch[i].child))) {
- n->branch[i] = *b;
+ /* copy branch */
+ n->branch[i].child = b->child;
+ RTreeCopyRect(&(n->branch[i].rect), &(b->rect), t);
n->count++;
break;
}
@@ -519,7 +561,9 @@
else if ((n)->level == 0) { /* leaf */
for (i = 0; i < maxkids; i++) { /* find empty branch */
if (n->branch[i].child.id == 0) {
- n->branch[i] = *b;
+ /* copy branch */
+ n->branch[i].child = b->child;
+ RTreeCopyRect(&(n->branch[i].rect), &(b->rect), t);
n->count++;
break;
}
@@ -563,7 +607,7 @@
static void RTreePrintBranch(struct RTree_Branch *b, int depth, struct RTree *t)
{
- RTreePrintRect(&(b->rect), depth);
+ RTreePrintRect(&(b->rect), depth, t);
RTreePrintNode(b->child.ptr, depth, t);
}
@@ -588,7 +632,7 @@
for (i = 0; i < maxkids; i++) {
if (n->level == 0) {
RTreeTabIn(depth);
- RTreePrintRect(&(n->branch[i].rect), depth);
+ RTreePrintRect(&(n->branch[i].rect), depth, t);
fprintf(stdout, "\t%d: data id = %d\n", i,
n->branch[i].child.id);
}
Modified: grass/trunk/lib/vector/rtree/rect.c
===================================================================
--- grass/trunk/lib/vector/rtree/rect.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/rect.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -27,23 +27,19 @@
#define BIG_NUM (FLT_MAX/4.0)
-#define Undefined(x) ((x)->boundary[0] > (x)->boundary[NUMDIMS])
+#define Undefined(x, t) ((x)->boundary[0] > (x)->boundary[t->ndims_alloc])
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#if 0
/*-----------------------------------------------------------------------------
| Create a new rectangle for a given tree
-----------------------------------------------------------------------------*/
void RTreeNewRect(struct RTree_Rect *r, struct RTree *t)
{
- r->boundary = (struct RTree_Rect *)malloc((size_t) t->nsides_alloc);
+ r->boundary = (RectReal *)malloc((size_t) t->nsides_alloc * sizeof(RectReal));
assert(r->boundary);
-
- RTreeInitRect(r, t);
}
-#endif
/*-----------------------------------------------------------------------------
| Initialize a rectangle to have all 0 coordinates.
@@ -52,25 +48,26 @@
{
register int i;
- for (i = 0; i < t->nsides; i++)
+ for (i = 0; i < t->nsides_alloc; i++)
r->boundary[i] = (RectReal) 0;
}
-
/*-----------------------------------------------------------------------------
| Return a rect whose first low side is higher than its opposite side -
| interpreted as an undefined rect.
-----------------------------------------------------------------------------*/
-struct RTree_Rect RTreeNullRect(void)
+void RTreeNullRect(struct RTree_Rect *r, struct RTree *t)
{
- struct RTree_Rect r;
register int i;
- r.boundary[0] = (RectReal) 1;
- r.boundary[NUMDIMS] = (RectReal) - 1;
- for (i = 1; i < NUMDIMS; i++)
- r.boundary[i] = r.boundary[i + NUMDIMS] = (RectReal) 0;
- return r;
+ assert(r);
+
+ r->boundary[0] = (RectReal) 1;
+ r->boundary[t->nsides - 1] = (RectReal) - 1;
+ for (i = 1; i < t->ndims; i++)
+ r->boundary[i] = r->boundary[i + t->ndims_alloc] = (RectReal) 0;
+
+ return;
}
@@ -139,7 +136,7 @@
/*-----------------------------------------------------------------------------
| Print out the data for a rectangle.
-----------------------------------------------------------------------------*/
-void RTreePrintRect(struct RTree_Rect *R, int depth)
+void RTreePrintRect(struct RTree_Rect *R, int depth, struct RTree *t)
{
register struct RTree_Rect *r = R;
register int i;
@@ -148,9 +145,9 @@
RTreeTabIn(depth);
fprintf(stdout, "rect:\n");
- for (i = 0; i < NUMDIMS; i++) {
+ for (i = 0; i < t->ndims_alloc; i++) {
RTreeTabIn(depth + 1);
- fprintf(stdout, "%f\t%f\n", r->boundary[i], r->boundary[i + NUMDIMS]);
+ fprintf(stdout, "%f\t%f\n", r->boundary[i], r->boundary[i + t->ndims_alloc]);
}
}
@@ -164,12 +161,13 @@
register RectReal volume = (RectReal) 1;
assert(r);
- if (Undefined(r))
+ if (Undefined(r, t))
return (RectReal) 0;
for (i = 0; i < t->ndims; i++)
- volume *= r->boundary[i + NUMDIMS] - r->boundary[i];
+ volume *= r->boundary[i + t->ndims_alloc] - r->boundary[i];
assert(volume >= 0.0);
+
return volume;
}
@@ -195,7 +193,7 @@
log_volume = dimension / 2.0 * log(M_PI) - log_gamma;
return exp(log_volume);
}
-static const double UnitSphereVolume = sphere_volume(NUMDIMS);
+static const double UnitSphereVolume = sphere_volume(20);
#else
@@ -248,7 +246,7 @@
RectReal maxsize = (RectReal) 0, c_size;
assert(r);
- if (Undefined(r))
+ if (Undefined(r, t))
return (RectReal) 0;
for (i = 0; i < t->ndims; i++) {
c_size = r->boundary[i + NUMDIMS] - r->boundary[i];
@@ -269,10 +267,10 @@
double sum_of_squares = 0, radius, half_extent;
assert(r);
- if (Undefined(r))
+ if (Undefined(r, t))
return (RectReal) 0;
for (i = 0; i < t->ndims; i++) {
- half_extent = (r->boundary[i + NUMDIMS] - r->boundary[i]) / 2;
+ half_extent = (r->boundary[i + t->ndims_alloc] - r->boundary[i]) / 2;
sum_of_squares += half_extent * half_extent;
}
@@ -290,7 +288,7 @@
RectReal j_extent, sum = (RectReal) 0;
assert(r);
- if (Undefined(r))
+ if (Undefined(r, t))
return (RectReal) 0;
for (i = 0; i < t->ndims; i++) {
@@ -299,7 +297,7 @@
for (j = 0; j < t->ndims; j++)
/* exclude i extent from product in this dimension */
if (i != j) {
- j_extent = r->boundary[j + NUMDIMS] - r->boundary[j];
+ j_extent = r->boundary[j + t->ndims_alloc] - r->boundary[j];
face_area *= j_extent;
}
@@ -321,7 +319,7 @@
assert(r);
for (i = 0; i < t->ndims; i++) {
- margin += r->boundary[i + NUMDIMS] - r->boundary[i];
+ margin += r->boundary[i + t->ndims_alloc] - r->boundary[i];
}
return margin;
@@ -331,33 +329,64 @@
/*-----------------------------------------------------------------------------
| Combine two rectangles, make one that includes both.
-----------------------------------------------------------------------------*/
-struct RTree_Rect RTreeCombineRect(struct RTree_Rect *r, struct RTree_Rect *rr, struct RTree *t)
+void RTreeCombineRect(struct RTree_Rect *r1, struct RTree_Rect *r2,
+ struct RTree_Rect *r3, struct RTree *t)
{
int i, j;
- struct RTree_Rect new_rect;
- assert(r && rr);
+ assert(r1 && r2 && r3);
- if (Undefined(r))
- return *rr;
+ if (Undefined(r1, t)) {
+ for (i = 0; i < t->nsides; i++)
+ r3->boundary[i] = r2->boundary[i];
+
+ return;
+ }
- if (Undefined(rr))
- return *r;
+ if (Undefined(r2, t)) {
+ for (i = 0; i < t->nsides; i++)
+ r3->boundary[i] = r1->boundary[i];
+
+ return;
+ }
for (i = 0; i < t->ndims; i++) {
- new_rect.boundary[i] = MIN(r->boundary[i], rr->boundary[i]);
- j = i + NUMDIMS;
- new_rect.boundary[j] = MAX(r->boundary[j], rr->boundary[j]);
+ r3->boundary[i] = MIN(r1->boundary[i], r2->boundary[i]);
+ j = i + t->ndims_alloc;
+ r3->boundary[j] = MAX(r1->boundary[j], r2->boundary[j]);
}
+ for (i = t->ndims; i < t->ndims_alloc; i++) {
+ r3->boundary[i] = 0;
+ j = i + t->ndims_alloc;
+ r3->boundary[j] = 0;
+ }
+}
- /* set remaining boundaries to zero */
- for (; i < NUMDIMS; i++) {
- new_rect.boundary[i] = MIN(r->boundary[i], rr->boundary[i]);
- j = i + NUMDIMS;
- new_rect.boundary[j] = MAX(r->boundary[j], rr->boundary[j]);
+
+/*-----------------------------------------------------------------------------
+| Expand first rectangle to cover second rectangle.
+-----------------------------------------------------------------------------*/
+void RTreeExpandRect(struct RTree_Rect *r1, struct RTree_Rect *r2,
+ struct RTree *t)
+{
+ int i, j;
+
+ assert(r1 && r2);
+
+ if (Undefined(r2, t))
+ return;
+
+ for (i = 0; i < t->ndims; i++) {
+ r1->boundary[i] = MIN(r1->boundary[i], r2->boundary[i]);
+ j = i + t->ndims_alloc;
+ r1->boundary[j] = MAX(r1->boundary[j], r2->boundary[j]);
}
- return new_rect;
+ for (i = t->ndims; i < t->ndims_alloc; i++) {
+ r1->boundary[i] = 0;
+ j = i + t->ndims_alloc;
+ r1->boundary[j] = 0;
+ }
}
@@ -371,7 +400,7 @@
assert(r && s);
for (i = 0; i < t->ndims; i++) {
- j = i + NUMDIMS; /* index for high sides */
+ j = i + t->ndims_alloc; /* index for high sides */
if (r->boundary[i] != s->boundary[i] ||
r->boundary[j] != s->boundary[j]) {
return 0;
@@ -382,7 +411,7 @@
/*-----------------------------------------------------------------------------
-| Decide whether two rectangles overlap.
+| Decide whether two rectangles overlap or touch.
-----------------------------------------------------------------------------*/
int RTreeOverlap(struct RTree_Rect *r, struct RTree_Rect *s, struct RTree *t)
{
@@ -391,7 +420,7 @@
assert(r && s);
for (i = 0; i < t->ndims; i++) {
- j = i + NUMDIMS; /* index for high sides */
+ j = i + t->ndims_alloc; /* index for high sides */
if (r->boundary[i] > s->boundary[j] ||
s->boundary[i] > r->boundary[j]) {
return FALSE;
@@ -411,16 +440,16 @@
assert(r && s);
/* undefined rect is contained in any other */
- if (Undefined(r))
+ if (Undefined(r, t))
return TRUE;
/* no rect (except an undefined one) is contained in an undef rect */
- if (Undefined(s))
+ if (Undefined(s, t))
return FALSE;
result = TRUE;
for (i = 0; i < t->ndims; i++) {
- j = i + NUMDIMS; /* index for high sides */
+ j = i + t->ndims_alloc; /* index for high sides */
result = result && r->boundary[i] >= s->boundary[i]
&& r->boundary[j] <= s->boundary[j];
}
Modified: grass/trunk/lib/vector/rtree/rtree.h
===================================================================
--- grass/trunk/lib/vector/rtree/rtree.h 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/rtree.h 2012-05-26 15:20:58 UTC (rev 51799)
@@ -19,13 +19,11 @@
#define _R_TREE_H_
#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
#include <grass/config.h> /* needed for LFS */
-#define NUMDIMS 3 /* maximum number of dimensions */
-#define NUMSIDES 2*NUMDIMS
-
typedef double RectReal;
/*-----------------------------------------------------------------------------
@@ -54,7 +52,7 @@
struct RTree_Rect
{
- RectReal boundary[NUMSIDES]; /* xmin,ymin,...,xmax,ymax,... */
+ RectReal *boundary; /* xmin,ymin,...,xmax,ymax,... */
};
struct RTree_Node; /* node for spatial index */
@@ -72,7 +70,7 @@
union RTree_Child child;
};
-struct RTree_Node /* node for spatial index */
+struct RTree_Node /* node for spatial index */
{
int count; /* number of branches */
int level; /* 0 is leaf, others positive */
@@ -96,16 +94,42 @@
typedef int rt_delete_fn(struct RTree_Rect *, union RTree_Child, struct RTree *);
typedef int rt_valid_child_fn(union RTree_Child *);
+/* temp vars for each tree */
+/* stacks used for non-recursive insertion/deletion */
+/* stack for file-based index */
+struct fstack
+{
+ struct RTree_Node sn; /* stack node */
+ int branch_id; /* branch number to follow down */
+ off_t pos; /* file position of stack node */
+};
+/* stack for memory-based index */
+struct mstack
+{
+ struct RTree_Node *sn; /* stack node pointer */
+ int branch_id; /* branch number to follow down */
+};
+
+/* temp vars for node splitting */
+struct RTree_PartitionVars {
+ int partition[MAXCARD + 1];
+ int total, minfill;
+ int taken[MAXCARD + 1];
+ int count[2];
+ struct RTree_Rect cover[2];
+ RectReal area[2];
+};
+
struct RTree
{
/* RTree setup info */
int fd; /* file descriptor */
unsigned char ndims; /* number of dimensions */
unsigned char nsides; /* number of sides = 2 * ndims */
- unsigned char nsides_alloc; /* number of sides = 2 * ndims */
+ unsigned char ndims_alloc; /* number of dimensions allocated */
+ unsigned char nsides_alloc; /* number of sides allocated = 2 * ndims allocated */
int nodesize; /* node size in bytes */
int branchsize; /* branch size in bytes */
- int rectsize; /* rectangle size in bytes */
/* RTree info, useful to calculate space requirements */
int n_nodes; /* number of nodes */
@@ -149,6 +173,22 @@
struct RTree_Node *root; /* pointer to root node */
+ /* internal variables, specific for each tree,
+ * allocated with tree initialization */
+ /* stacks for tree traversal */
+ struct mstack ms[MAXLEVEL];
+ struct fstack fs[MAXLEVEL];
+
+ /* variables for splitting / forced reinsertion */
+ struct RTree_PartitionVars p;
+ struct RTree_Branch BranchBuf[MAXCARD + 1];
+
+ struct RTree_Branch tmpb1, tmpb2, c;
+ int BranchCount;
+
+ struct RTree_Rect rect_0, rect_1, upperrect, orect;
+ RectReal *center_n;
+
off_t rootpos; /* root node position in file */
};
@@ -167,6 +207,8 @@
void RTreeFreeNode(struct RTree_Node *);
void RTreeDestroyNode(struct RTree_Node *, int);
+void RTreeNewRect(struct RTree_Rect *, struct RTree *);
+
/* RTree IO */
size_t RTreeReadNode(struct RTree_Node *, off_t, struct RTree *);
size_t RTreeWriteNode(struct RTree_Node *, struct RTree *);
Modified: grass/trunk/lib/vector/rtree/split.c
===================================================================
--- grass/trunk/lib/vector/rtree/split.c 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/split.c 2012-05-26 15:20:58 UTC (rev 51799)
@@ -17,9 +17,12 @@
*
***********************************************************************/
+#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <float.h>
+/* remove after debug */
+#include <grass/gis.h>
#include "index.h"
#include "card.h"
#include "split.h"
@@ -28,19 +31,11 @@
#define DBL_MAX 1.797693E308 /* DBL_MAX approximation */
#endif
-struct RTree_Branch BranchBuf[MAXCARD + 1];
-int BranchCount;
-struct RTree_Rect CoverSplit;
-RectReal CoverSplitArea;
-
-/* variables for finding a partition */
-struct RTree_PartitionVars Partitions[1];
-
/*----------------------------------------------------------------------
| Load branch buffer with branches from full node plus the extra branch.
----------------------------------------------------------------------*/
static void RTreeGetBranches(struct RTree_Node *n, struct RTree_Branch *b,
- struct RTree *t)
+ RectReal *CoverSplitArea, struct RTree *t)
{
int i, maxkids = 0;
@@ -49,7 +44,7 @@
/* load the branch buffer */
for (i = 0; i < maxkids; i++) {
assert(t->valid_child(&(n->branch[i].child))); /* n should have every entry full */
- BranchBuf[i] = n->branch[i];
+ RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
}
}
else {
@@ -57,20 +52,20 @@
/* 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];
+ RTreeCopyBranch(&(t->BranchBuf[i]), &(n->branch[i]), t);
}
}
- BranchBuf[maxkids] = *b;
- BranchCount = maxkids + 1;
+ RTreeCopyBranch(&(t->BranchBuf[maxkids]), b, t);
+ t->BranchCount = maxkids + 1;
if (METHOD == 0) { /* quadratic split */
/* calculate rect containing all in the set */
- CoverSplit = BranchBuf[0].rect;
+ RTreeCopyRect(&(t->orect), &(t->BranchBuf[0].rect), t);
for (i = 1; i < maxkids + 1; i++) {
- CoverSplit = RTreeCombineRect(&CoverSplit, &BranchBuf[i].rect, t);
+ RTreeExpandRect(&(t->orect), &(t->BranchBuf[i].rect), t);
}
- CoverSplitArea = RTreeRectSphericalVolume(&CoverSplit, t);
+ *CoverSplitArea = RTreeRectSphericalVolume(&(t->orect), t);
}
RTreeInitNode(t, n, NODETYPE(n->level, t->fd));
@@ -89,11 +84,10 @@
if (METHOD == 0) {
if (p->count[group] == 0)
- p->cover[group] = BranchBuf[i].rect;
+ RTreeCopyRect(&(p->cover[group]), &(t->BranchBuf[i].rect), t);
else
- p->cover[group] =
- RTreeCombineRect(&BranchBuf[i].rect, &p->cover[group], t);
- p->area[group] = RTreeRectSphericalVolume(&p->cover[group], t);
+ RTreeExpandRect(&(p->cover[group]), &(t->BranchBuf[i].rect), t);
+ p->area[group] = RTreeRectSphericalVolume(&(p->cover[group]), t);
}
p->count[group]++;
}
@@ -109,23 +103,22 @@
| Pick the two that waste the most area if covered by a single
| rectangle.
----------------------------------------------------------------------*/
-static void RTreePickSeeds(struct RTree_PartitionVars *p, struct RTree *t)
+static void RTreePickSeeds(struct RTree_PartitionVars *p, RectReal CoverSplitArea, struct RTree *t)
{
int i, j, seed0 = 0, seed1 = 0;
RectReal worst, waste, area[MAXCARD + 1];
for (i = 0; i < p->total; i++)
- area[i] = RTreeRectSphericalVolume(&BranchBuf[i].rect, t);
+ area[i] = RTreeRectSphericalVolume(&(t->BranchBuf[i]).rect, t);
worst = -CoverSplitArea - 1;
for (i = 0; i < p->total - 1; i++) {
for (j = i + 1; j < p->total; j++) {
- struct RTree_Rect one_rect;
- one_rect = RTreeCombineRect(&BranchBuf[i].rect,
- &BranchBuf[j].rect, t);
+ RTreeCombineRect(&(t->BranchBuf[i].rect), &(t->BranchBuf[j].rect),
+ &(t->orect), t);
waste =
- RTreeRectSphericalVolume(&one_rect, t) - area[i] - area[j];
+ RTreeRectSphericalVolume(&(t->orect), t) - area[i] - area[j];
if (waste > worst) {
worst = waste;
seed0 = i;
@@ -149,22 +142,25 @@
for (i = 0; i < p->total; i++) {
assert(p->partition[i] == 0 || p->partition[i] == 1);
if (p->partition[i] == 0)
- RTreeAddBranch(&BranchBuf[i], n, NULL, NULL, NULL, NULL, t);
+ RTreeAddBranch(&(t->BranchBuf[i]), n, NULL, NULL, NULL, NULL, t);
else if (p->partition[i] == 1)
- RTreeAddBranch(&BranchBuf[i], q, NULL, NULL, NULL, NULL, t);
+ RTreeAddBranch(&(t->BranchBuf[i]), q, NULL, NULL, NULL, NULL, t);
}
}
/*----------------------------------------------------------------------
| Initialize a PartitionVars structure.
----------------------------------------------------------------------*/
-void RTreeInitPVars(struct RTree_PartitionVars *p, int maxrects, int minfill)
+void RTreeInitPVars(struct RTree_PartitionVars *p, int maxrects, int minfill, struct RTree *t)
{
int i;
p->count[0] = p->count[1] = 0;
- p->cover[0] = p->cover[1] = RTreeNullRect();
- p->area[0] = p->area[1] = (RectReal) 0;
+ if (METHOD == 0) {
+ RTreeNullRect(&(p->cover[0]), t);
+ RTreeNullRect(&(p->cover[1]), t);
+ p->area[0] = p->area[1] = (RectReal) 0;
+ }
p->total = maxrects;
p->minfill = minfill;
for (i = 0; i < maxrects; i++) {
@@ -177,7 +173,7 @@
| Print out data for a partition from PartitionVars struct.
| Unused, for debugging only
----------------------------------------------------------------------*/
-static void RTreePrintPVars(struct RTree_PartitionVars *p)
+static void RTreePrintPVars(struct RTree_PartitionVars *p, struct RTree *t, RectReal CoverSplitArea)
{
int i;
@@ -206,10 +202,10 @@
(float)CoverSplitArea / (p->area[0] + p->area[1]));
}
fprintf(stdout, "cover[0]:\n");
- RTreePrintRect(&p->cover[0], 0);
+ RTreePrintRect(&p->cover[0], 0, t);
fprintf(stdout, "cover[1]:\n");
- RTreePrintRect(&p->cover[1], 0);
+ RTreePrintRect(&p->cover[1], 0, t);
}
/*----------------------------------------------------------------------
@@ -227,14 +223,18 @@
| These last are the ones that can go in either group most easily.
----------------------------------------------------------------------*/
static void RTreeMethodZero(struct RTree_PartitionVars *p, int minfill,
- struct RTree *t)
+ RectReal CoverSplitArea, struct RTree *t)
{
int i;
RectReal biggestDiff;
int group, chosen = 0, betterGroup = 0;
+ struct RTree_Rect *r, *rect_0, *rect_1;
- RTreeInitPVars(p, BranchCount, minfill);
- RTreePickSeeds(p, t);
+ RTreeInitPVars(p, t->BranchCount, minfill, t);
+ RTreePickSeeds(p, CoverSplitArea, t);
+
+ rect_0 = &(t->rect_0);
+ rect_1 = &(t->rect_1);
while (p->count[0] + p->count[1] < p->total
&& p->count[0] < p->total - p->minfill
@@ -242,14 +242,13 @@
biggestDiff = (RectReal) - 1.;
for (i = 0; i < p->total; i++) {
if (!p->taken[i]) {
- struct RTree_Rect *r, rect_0, rect_1;
RectReal growth0, growth1, diff;
- r = &BranchBuf[i].rect;
- rect_0 = RTreeCombineRect(r, &p->cover[0], t);
- rect_1 = RTreeCombineRect(r, &p->cover[1], t);
- growth0 = RTreeRectSphericalVolume(&rect_0, t) - p->area[0];
- growth1 = RTreeRectSphericalVolume(&rect_1, t) - p->area[1];
+ r = &(t->BranchBuf[i].rect);
+ RTreeCombineRect(r, &(p->cover[0]), rect_0, t);
+ RTreeCombineRect(r, &(p->cover[1]), rect_1, t);
+ growth0 = RTreeRectSphericalVolume(rect_0, t) - p->area[0];
+ growth1 = RTreeRectSphericalVolume(rect_1, t) - p->area[1];
diff = growth1 - growth0;
if (diff >= 0)
group = 0;
@@ -298,13 +297,11 @@
/*----------------------------------------------------------------------
| swap branches
----------------------------------------------------------------------*/
-static void RTreeSwapBranches(struct RTree_Branch *a, struct RTree_Branch *b)
+static void RTreeSwapBranches(struct RTree_Branch *a, struct RTree_Branch *b, struct RTree *t)
{
- struct RTree_Branch c;
-
- c = *a;
- *a = *b;
- *b = c;
+ RTreeCopyBranch(&(t->c), a, t);
+ RTreeCopyBranch(a, b, t);
+ RTreeCopyBranch(b, &(t->c), t);
}
/*----------------------------------------------------------------------
@@ -327,12 +324,12 @@
/*----------------------------------------------------------------------
| check if BranchBuf is sorted along given axis (dimension)
----------------------------------------------------------------------*/
-static int RTreeBranchBufIsSorted(int first, int last, int side)
+static int RTreeBranchBufIsSorted(int first, int last, int side, struct RTree *t)
{
int i;
for (i = first; i < last; i++) {
- if (RTreeCompareBranches(&(BranchBuf[i]), &(BranchBuf[i + 1]), side)
+ if (RTreeCompareBranches(&(t->BranchBuf[i]), &(t->BranchBuf[i + 1]), side)
== 1)
return 0;
}
@@ -343,21 +340,21 @@
/*----------------------------------------------------------------------
| partition BranchBuf for quicksort along given axis (dimension)
----------------------------------------------------------------------*/
-static int RTreePartitionBranchBuf(int first, int last, int side)
+static int RTreePartitionBranchBuf(int first, int last, int side, struct RTree *t)
{
int pivot, mid = (first + last) / 2;
int larger, smaller;
if (last - first == 1) { /* only two items in list */
if (RTreeCompareBranches
- (&(BranchBuf[first]), &(BranchBuf[last]), side) == 1) {
- RTreeSwapBranches(&(BranchBuf[first]), &(BranchBuf[last]));
+ (&(t->BranchBuf[first]), &(t->BranchBuf[last]), side) == 1) {
+ RTreeSwapBranches(&(t->BranchBuf[first]), &(t->BranchBuf[last]), t);
}
return last;
}
/* larger of two */
- if (RTreeCompareBranches(&(BranchBuf[first]), &(BranchBuf[mid]), side)
+ if (RTreeCompareBranches(&(t->BranchBuf[first]), &(t->BranchBuf[mid]), side)
== 1) {
larger = pivot = first;
smaller = mid;
@@ -367,11 +364,11 @@
smaller = first;
}
- if (RTreeCompareBranches(&(BranchBuf[larger]), &(BranchBuf[last]), side)
+ if (RTreeCompareBranches(&(t->BranchBuf[larger]), &(t->BranchBuf[last]), side)
== 1) {
/* larger is largest, get the larger of smaller and last */
if (RTreeCompareBranches
- (&(BranchBuf[smaller]), &(BranchBuf[last]), side) == 1) {
+ (&(t->BranchBuf[smaller]), &(t->BranchBuf[last]), side) == 1) {
pivot = smaller;
}
else {
@@ -380,16 +377,16 @@
}
if (pivot != last) {
- RTreeSwapBranches(&(BranchBuf[pivot]), &(BranchBuf[last]));
+ RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[last]), t);
}
pivot = first;
while (first < last) {
if (RTreeCompareBranches
- (&(BranchBuf[first]), &(BranchBuf[last]), side) != 1) {
+ (&(t->BranchBuf[first]), &(t->BranchBuf[last]), side) != 1) {
if (pivot != first) {
- RTreeSwapBranches(&(BranchBuf[pivot]), &(BranchBuf[first]));
+ RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[first]), t);
}
pivot++;
}
@@ -397,7 +394,7 @@
}
if (pivot != last) {
- RTreeSwapBranches(&(BranchBuf[pivot]), &(BranchBuf[last]));
+ RTreeSwapBranches(&(t->BranchBuf[pivot]), &(t->BranchBuf[last]), t);
}
return pivot;
@@ -406,13 +403,13 @@
/*----------------------------------------------------------------------
| quicksort BranchBuf along given side
----------------------------------------------------------------------*/
-static void RTreeQuicksortBranchBuf(int side)
+static void RTreeQuicksortBranchBuf(int side, struct RTree *t)
{
int pivot, first, last;
int s_first[MAXCARD + 1], s_last[MAXCARD + 1], stacksize;
s_first[0] = 0;
- s_last[0] = BranchCount - 1;
+ s_last[0] = t->BranchCount - 1;
stacksize = 1;
@@ -422,9 +419,9 @@
first = s_first[stacksize];
last = s_last[stacksize];
if (first < last) {
- if (!RTreeBranchBufIsSorted(first, last, side)) {
+ if (!RTreeBranchBufIsSorted(first, last, side, t)) {
- pivot = RTreePartitionBranchBuf(first, last, side);
+ pivot = RTreePartitionBranchBuf(first, last, side, t);
s_first[stacksize] = first;
s_last[stacksize] = pivot - 1;
@@ -454,15 +451,30 @@
int maxkids, struct RTree *t)
{
int i, j, k, l, s;
- int axis = 0, best_axis = 0, side = 0, best_side[NUMDIMS];
- int best_cut[NUMDIMS];
+ int axis = 0, best_axis = 0, side = 0;
RectReal margin, smallest_margin = 0;
- struct RTree_Rect *r1, *r2, testrect1, testrect2, upperrect, orect;
+ struct RTree_Rect *r1, *r2;
+ struct RTree_Rect *rect_0, *rect_1, *orect, *upperrect;
int minfill1 = minfill - 1;
RectReal overlap, vol, smallest_overlap = -1, smallest_vol = -1;
- RTreeInitPVars(p, BranchCount, minfill);
+ static int *best_cut = NULL, *best_side = NULL;
+ static int one_init = 0;
+
+ if (!one_init) {
+ best_cut = (int *)malloc(t->ndims_alloc * sizeof(int));
+ best_side = (int *)malloc(t->ndims_alloc * sizeof(int));
+ one_init = 1;
+ }
+ rect_0 = &(t->rect_0);
+ rect_1 = &(t->rect_1);
+ orect = &(t->orect);
+ upperrect = &(t->upperrect);
+
+ RTreeInitPVars(p, t->BranchCount, minfill, t);
+ RTreeInitRect(orect, t);
+
margin = DBL_MAX;
/* choose split axis */
@@ -478,38 +490,38 @@
/* first lower then upper bounds for each axis */
for (s = 0; s < 2; s++) {
- RTreeQuicksortBranchBuf(i + s * NUMDIMS);
+ RTreeQuicksortBranchBuf(i + s * t->ndims_alloc, t);
side = s;
- testrect1 = BranchBuf[0].rect;
- upperrect = BranchBuf[maxkids].rect;
+ RTreeCopyRect(rect_0, &(t->BranchBuf[0].rect), t);
+ RTreeCopyRect(upperrect, &(t->BranchBuf[maxkids].rect), t);
for (j = 1; j < minfill1; j++) {
- r1 = &BranchBuf[j].rect;
- testrect1 = RTreeCombineRect(&testrect1, r1, t);
- r2 = &BranchBuf[maxkids - j].rect;
- upperrect = RTreeCombineRect(&upperrect, r2, t);
+ r1 = &(t->BranchBuf[j].rect);
+ RTreeExpandRect(rect_0, r1, t);
+ r2 = &(t->BranchBuf[maxkids - j].rect);
+ RTreeExpandRect(upperrect, r2, t);
}
- r2 = &BranchBuf[maxkids - minfill1].rect;
- upperrect = RTreeCombineRect(&upperrect, r2, t);
+ r2 = &(t->BranchBuf[maxkids - minfill1].rect);
+ RTreeExpandRect(upperrect, r2, t);
/* check distributions for this axis, adhere the minimum node fill */
- for (j = minfill1; j < BranchCount - minfill; j++) {
+ for (j = minfill1; j < t->BranchCount - minfill; j++) {
- r1 = &BranchBuf[j].rect;
- testrect1 = RTreeCombineRect(&testrect1, r1, t);
+ r1 = &(t->BranchBuf[j].rect);
+ RTreeExpandRect(rect_0, r1, t);
- testrect2 = upperrect;
- for (k = j + 1; k < BranchCount - minfill; k++) {
- r2 = &BranchBuf[k].rect;
- testrect2 = RTreeCombineRect(&testrect2, r2, t);
+ RTreeCopyRect(rect_1, upperrect, t);
+ for (k = j + 1; k < t->BranchCount - minfill; k++) {
+ r2 = &(t->BranchBuf[k].rect);
+ RTreeExpandRect(rect_1, r2, t);
}
/* the margin is the sum of the lengths of the edges of a rectangle */
margin =
- RTreeRectMargin(&testrect1, t) +
- RTreeRectMargin(&testrect2, t);
+ RTreeRectMargin(rect_0, t) +
+ RTreeRectMargin(rect_1, t);
/* remember best axis */
if (margin <= smallest_margin) {
@@ -524,31 +536,31 @@
for (k = 0; k < t->ndims; k++) {
/* no overlap */
- if (testrect1.boundary[k] > testrect2.boundary[k + NUMDIMS] ||
- testrect1.boundary[k + NUMDIMS] < testrect2.boundary[k]) {
+ if (rect_0->boundary[k] > rect_1->boundary[k + t->ndims_alloc] ||
+ rect_0->boundary[k + t->ndims_alloc] < rect_1->boundary[k]) {
overlap = 0;
break;
}
/* get overlap */
else {
- if (testrect1.boundary[k] > testrect2.boundary[k])
- orect.boundary[k] = testrect1.boundary[k];
+ if (rect_0->boundary[k] > rect_1->boundary[k])
+ orect->boundary[k] = rect_0->boundary[k];
else
- orect.boundary[k] = testrect2.boundary[k];
+ orect->boundary[k] = rect_1->boundary[k];
- l = k + NUMDIMS;
- if (testrect1.boundary[l] < testrect2.boundary[l])
- orect.boundary[l] = testrect1.boundary[l];
+ l = k + t->ndims_alloc;
+ if (rect_0->boundary[l] < rect_1->boundary[l])
+ orect->boundary[l] = rect_0->boundary[l];
else
- orect.boundary[l] = testrect2.boundary[l];
+ orect->boundary[l] = rect_1->boundary[l];
}
}
if (overlap)
- overlap = RTreeRectVolume(&orect, t);
+ overlap = RTreeRectVolume(orect, t);
vol =
- RTreeRectVolume(&testrect1, t) +
- RTreeRectVolume(&testrect2, t);
+ RTreeRectVolume(rect_0, t) +
+ RTreeRectVolume(rect_1, t);
/* get best cut for this axis */
if (overlap <= smallest_overlap) {
@@ -571,14 +583,14 @@
/* Use best distribution to classify branches */
if (best_axis != axis || best_side[best_axis] != side)
- RTreeQuicksortBranchBuf(best_axis + best_side[best_axis] * NUMDIMS);
+ RTreeQuicksortBranchBuf(best_axis + best_side[best_axis] * t->ndims_alloc, t);
best_cut[best_axis]++;
for (i = 0; i < best_cut[best_axis]; i++)
RTreeClassify(i, 0, p, t);
- for (i = best_cut[best_axis]; i < BranchCount; i++)
+ for (i = best_cut[best_axis]; i < t->BranchCount; i++)
RTreeClassify(i, 1, p, t);
assert(p->count[0] + p->count[1] == p->total);
@@ -595,19 +607,20 @@
struct RTree_Node *nn, struct RTree *t)
{
struct RTree_PartitionVars *p;
+ RectReal CoverSplitArea;
int level;
/* load all the branches into a buffer, initialize old node */
level = n->level;
- RTreeGetBranches(n, b, t);
+ RTreeGetBranches(n, b, &CoverSplitArea, t);
/* find partition */
- p = &Partitions[0];
+ p = &(t->p);
if (METHOD == 1) /* R* split */
- RTreeMethodOne(p, MINFILL(level, t), MAXKIDS(level, t), t);
+ RTreeMethodOne(&(t->p), MINFILL(level, t), MAXKIDS(level, t), t);
else
- RTreeMethodZero(p, MINFILL(level, t), t);
+ RTreeMethodZero(&(t->p), MINFILL(level, t), CoverSplitArea, t);
/*
* put branches from buffer into 2 nodes
Modified: grass/trunk/lib/vector/rtree/split.h
===================================================================
--- grass/trunk/lib/vector/rtree/split.h 2012-05-26 15:14:37 UTC (rev 51798)
+++ grass/trunk/lib/vector/rtree/split.h 2012-05-26 15:20:58 UTC (rev 51799)
@@ -24,17 +24,4 @@
/* METHOD 1: R*-Tree split */
#define METHOD 1
-struct RTree_PartitionVars {
- int partition[MAXCARD + 1];
- int total, minfill;
- int taken[MAXCARD + 1];
- int count[2];
- struct RTree_Rect cover[2];
- RectReal area[2];
-};
-
-
-/* variables for finding a partition */
-extern struct RTree_PartitionVars Partitions[1];
-
-extern void RTreeInitPVars(struct RTree_PartitionVars *, int, int);
+void RTreeInitPVars(struct RTree_PartitionVars *, int, int, struct RTree *);
More information about the grass-commit
mailing list