Ejemplo n.º 1
0
static int RTreePickLeafBranch(struct RTree_Rect *r, struct RTree_Node *n, struct RTree *t)
{
    struct RTree_Rect *rr;
    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;

    /* 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 (t->valid_child(&(n->branch[i].child))) {
	    rr = &n->branch[i].rect;
	    tmp_rect = RTreeCombineRect(r, rr, t);
	    area = RTreeRectSphericalVolume(rr, t);
	    increase = RTreeRectSphericalVolume(&tmp_rect, 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);
		}
	    }

	    if (overlap < bestoverlap) {
		best = i;
		bestoverlap = overlap;
		bestArea = area;
		bestIncr = increase;
	    }
	    else if (overlap == bestoverlap) {
		/* resolve ties */
		if (increase < bestIncr) {
		    best = i;
		    bestArea = area;
		    bestIncr = increase;
		}
		else if (increase == bestIncr && area < bestArea) {
		    best = i;
		    bestArea = area;
		}
	    }
	}
    }

    return best;
}
Ejemplo n.º 2
0
/*
 * Delete a rectangle from non-root part of an index structure.
 * Called by RTreeDeleteRect.  Descends tree recursively,
 * merges branches on the way back up.
 * Returns 1 if record not found, 0 if success.
 */
static int
RTreeDeleteRect2(struct Rect *R, long Tid, struct Node *N, struct ListNode **Ee)
{
        register struct Rect *r = R;
        register long tid = Tid;
        register struct Node *n = N;
        register struct ListNode **ee = Ee;
        register int i;

        assert(r && n && ee);
        assert(tid >= 0);
        assert(n->level >= 0);

        if (n->level > 0)  /* not a leaf node */
        {
            for (i = 0; i < NODECARD; i++)
            {
                if (n->branch[i].child && RTreeOverlap(r, &(n->branch[i].rect)))
                {
                        if (!RTreeDeleteRect2(r, tid, n->branch[i].child, ee))
                        {
                                if (n->branch[i].child->count >= MinNodeFill) {
                                        n->branch[i].rect = RTreeNodeCover(
                                                n->branch[i].child);
                                }
                                else
                                {
                                        /* not enough entries in child, eliminate child node */
                                        RTreeReInsert(n->branch[i].child, ee);
                                        RTreeDisconnectBranch(n, i);
                                }
                                return 0;
                        }
                }
            }
            return 1;
        }
        else  /* a leaf node */
        {
                for (i = 0; i < LEAFCARD; i++)
                {
                        if (n->branch[i].child &&
                            (struct Node *)(n->branch[i].child) == (struct Node *) tid)
                        {
                                RTreeDisconnectBranch(n, i);
                                return 0;
                        }
                }
                return 1;
        }
}
Ejemplo n.º 3
0
/*
 * Search in an index tree for all data retangles that
 * overlap the argument rectangle.
 * Return the number of qualifying data rects.
 */
int RTreeSearchF(struct RTree *t, struct RTree_Rect *r,
		 SearchHitCallback *shcb, void *cbarg)
{
    struct RTree_Node *n;
    int hitCount = 0, notfound, currlevel;
    int i;
    int top = 0;
    struct nstack *s = t->ns;

    /* stack size of t->rootlevel + 1 is enough because of depth first search */
    /* only one node per level on stack at any given time */

    /* add root node position to stack */
    currlevel = t->rootlevel;
    s[top].pos = t->rootpos;
    s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
    s[top].branch_id = i = 0;
    
    while (top >= 0) {
	n = s[top].sn;
	if (s[top].sn->level > 0) {		/* this is an internal node in the tree */
	    notfound = 1;
	    currlevel = s[top].sn->level - 1;
	    for (i = s[top].branch_id; i < t->nodecard; i++) {
		if (s[top].sn->branch[i].child.pos > -1 &&
		    RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
		    s[top++].branch_id = i + 1;
		    /* add next node to stack */
		    s[top].pos = n->branch[i].child.pos;
		    s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
		    s[top].branch_id = 0;
		    notfound = 0;
		    break;
		}
	    }
	    if (notfound) {
		/* nothing else found, go back up */
		s[top].branch_id = t->nodecard;
		top--;
	    }
	}
	else {			/* this is a leaf node */
	    for (i = 0; i < t->leafcard; i++) {
		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(s[top].sn->branch[i].child.id,
			          &(s[top].sn->branch[i].rect), cbarg)) {
			    /* callback wants to terminate search early */
			    return hitCount;
			}
		    }
		}
	    }
	    top--;
	}
    }

    return hitCount;
}
Ejemplo n.º 4
0
/*
 * Delete a rectangle from non-root part of an index structure.
 * Called by RTreeDeleteRect.  Descends tree non-recursively,
 * merges branches on the way back up.
 * Returns 1 if record not found, 0 if success.
 */
static int
RTreeDeleteRect2F(struct RTree_Rect *r, union RTree_Child child, struct RTree *t,
		 struct RTree_ListNode **ee)
{
    int i, notfound = 1, currlevel;
    struct RTree_Node *n;
    int top = 0, down = 0;
    int minfill;
    struct nstack *s = t->ns;

    struct RTree_Rect *nr = &(t->orect);

    /* add root node position to stack */
    currlevel = t->rootlevel;
    s[top].pos = t->rootpos;
    s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
    s[top].branch_id = 0;

    while (notfound && top >= 0) {
	/* go down to level 0, remember path */
	if (s[top].sn->level > 0) {
	    n = s[top].sn;
	    currlevel = s[top].sn->level - 1;
	    for (i = s[top].branch_id; i < t->nodecard; i++) {
		if (n->branch[i].child.pos > -1 &&
		    RTreeOverlap(r, &(n->branch[i].rect), t)) {
		    s[top++].branch_id = i + 1;
		    /* add next node to stack */
		    s[top].pos = n->branch[i].child.pos;
		    s[top].sn = RTreeGetNode(s[top].pos, currlevel, t);
		    s[top].branch_id = 0;

		    notfound = 0;
		    break;
		}
	    }
	    if (notfound) {
		/* nothing else found, go back up */
		s[top].branch_id = t->nodecard;
		top--;
	    }
	    else       /* found a way down but not yet the item */
		notfound = 1;
	}
	else {
	    for (i = 0; i < t->leafcard; i++) {
		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);
		    RTreeNodeChanged(s[top].sn, s[top].pos, t);
		    t->n_leafs--;
		    notfound = 0;
		    break;
		}
	    }
	    if (notfound)    /* continue searching */
		top--;
	}
    }

    if (notfound) {
	return notfound;
    }

    /* go back up */
    while (top) {
	down = top;
	top--;
	i = s[top].branch_id - 1;

	minfill = (s[down].sn->level ? t->min_node_fill : t->min_leaf_fill);
	if (s[down].sn->count >= minfill) {
	    /* just update node cover */
	    RTreeNodeCover(s[down].sn, nr, t);
	    /* rewrite rect */
	    if (!RTreeCompareRect(nr, &(s[top].sn->branch[i].rect), t)) {
		RTreeCopyRect(&(s[top].sn->branch[i].rect), nr, t);
		RTreeNodeChanged(s[top].sn, s[top].pos, t);
	    }
	}
	else {
	    /* not enough entries in child, eliminate child node */
	    n = RTreeAllocNode(t, s[down].sn->level);
	    /* copy node */
	    RTreeCopyNode(n, s[down].sn, t);
	    RTreeAddNodePos(s[down].pos, s[down].sn->level, t);
	    RTreeReInsertNode(n, ee);
	    RTreeDisconnectBranch(s[top].sn, i, t);

	    RTreeNodeChanged(s[top].sn, s[top].pos, t);
	}
    }

    return notfound;
}
Ejemplo n.º 5
0
/*!
   \brief Search spatial index file
   Can't use regular RTreeSearch() here because sidx must be read
   with dig__fread_port_*() functions

   \param t pointer to RTree
   \param r search rectangle
   \param shcb user-provided callback
   \param cbarg argument for shcb
   \param Plus pointer to Plus_head structure

   \return number of qualifying rectangles
 */
int rtree_search(struct RTree *t, struct RTree_Rect *r,
                 SearchHitCallback shcb, void *cbarg, struct Plus_head *Plus)
{
    int hitCount = 0, found;
    /* int j, maxcard; */
    int i;
    struct spidxpstack s[MAXLEVEL];
    int top = 0, level;
    off_t lastpos;

    assert(r);
    assert(t);

    /* stack size of t->rootlevel + 1 is enough because of depth first search */
    /* only one node per level on stack at any given time */

    dig_set_cur_port(&(Plus->spidx_port));

    /* add root node position to stack */
    s[top].sn = rtree_get_node(t->rootpos, t->rootlevel, t, Plus);
#if 0
    dig_fseek(&(Plus->spidx_fp), t->rootpos, SEEK_SET);
    /* read with dig__fread_port_* fns */
    dig__fread_port_I(&(s[top].sn.count), 1, &(Plus->spidx_fp));
    dig__fread_port_I(&(s[top].sn.level), 1, &(Plus->spidx_fp));
    maxcard = t->rootlevel ? t->nodecard : t->leafcard;
    for (j = 0; j < maxcard; j++) {
	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES,
			  &(Plus->spidx_fp));
	dig__fread_port_O(&(s[top].pos[j]), 1, &(Plus->spidx_fp),
			  Plus->spidx_port.off_t_size);
	/* leaf node: vector object IDs are stored in child.id */
	if (s[top].sn.level == 0) {
	    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
	}
	else {
	    s[top].sn.branch[j].child.pos = s[top].pos[j];
	}
    }
#endif

    s[top].branch_id = i = 0;

    while (top >= 0) {
	level = s[top].sn->level;
	if (level > 0) {	/* this is an internal node in the tree */
	    found = 1;
	    for (i = s[top].branch_id; i < t->nodecard; i++) {
		lastpos = s[top].sn->branch[i].child.pos;
		if (lastpos > 0 &&
		    RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
		    s[top++].branch_id = i + 1;
		    s[top].sn = rtree_get_node(lastpos, level - 1, t, Plus);
		    
#if 0
		    dig_fseek(&(Plus->spidx_fp), lastpos, SEEK_SET);
		    /* read with dig__fread_port_* fns */
		    dig__fread_port_I(&(s[top].sn.count), 1,
				      &(Plus->spidx_fp));
		    dig__fread_port_I(&(s[top].sn.level), 1,
				      &(Plus->spidx_fp));
		    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
		    for (j = 0; j < maxcard; j++) {
			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
					  NUMSIDES, &(Plus->spidx_fp));
			dig__fread_port_O(&(s[top].pos[j]), 1,
					  &(Plus->spidx_fp),
					  Plus->spidx_port.off_t_size);
			if (s[top].sn.level == 0) {
			    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
			}
			else {
			    s[top].sn.branch[j].child.pos = s[top].pos[j];
			}
		    }
#endif
		    s[top].branch_id = 0;
		    found = 0;
		    break;
		}
	    }
	    if (found) {
		/* nothing else found, go back up */
		s[top].branch_id = t->nodecard;
		top--;
	    }
	}
	else {			/* this is a leaf node */
	    for (i = 0; i < t->leafcard; i++) {
		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.id,
				  &s[top].sn->branch[i].rect, cbarg)) {
			    /* callback wants to terminate search early */
			    return hitCount;
			}
		    }
		}
	    }
	    top--;
	}
    }

    return hitCount;
}
Ejemplo n.º 6
0
/*
 * Search in an index tree or subtree for all data rectangles that
 * overlap the argument rectangle.
 * Return the number of qualifying data rects.
 */
int RTreeSearch(struct Node *N, struct Rect *R, SearchHitCallback shcb, void* cbarg, int mode)
{
        register struct Node *n = N;
        register struct Rect *r = R; /* NOTE: Suspected bug was R sent in as Node* and cast to Rect* here.*/
                                     /*        Fix not yet tested. */
        register int hitCount = 0;
        register int i;

        long  index;

        int sdebug = 0;

        if(mode == ID)
        {
           index = (long)N;

           n = &nodes[index];
        }

        if(sdebug)
        {
           if (n->level > 0)
              printf("\nChecking internal node %ld\n", index);
           else
              printf("\nChecking leaf node %ld\n", index);
        }

        assert(n);
        assert(n->level >= 0);
        assert(r);

        if (n->level > 0) /* this is an internal node in the tree */
        {
                for (i=0; i<NODECARD; i++)
                {
                        if (sdebug && n->branch[i].child)
                        {
                                printf("\nNODECARD %ld\n", (long)n->branch[i].child);
                                fflush(stdout);
                        }

                        if (n->branch[i].child &&
                            RTreeOverlap(r,&n->branch[i].rect))
                        {
                                if(RTreeContained(&n->branch[i].rect, r))
                                   hitCount += RTreeSearch(n->branch[i].child, R, shcb, cbarg, mode);

                                else
                                   hitCount += RTreeSearch(n->branch[i].child, R, shcb, cbarg, mode);
                        }
                }
        }
        else /* this is a leaf node */
        {
                for (i=0; i<LEAFCARD; i++)
                {
                        if (sdebug && n->branch[i].child)
                        {
                                printf("\nLEAFCARD %ld\n", (long)n->branch[i].child);
                                fflush(stdout);
                        }

                        if (n->branch[i].child &&
                            RTreeOverlap(r,&n->branch[i].rect))
                        {
                                hitCount++;

                                if(sdebug)
                                   printf("---> Found\n");

                                if(shcb) /* call the user-provided callback */
                                        if( ! shcb((long)n->branch[i].child, cbarg))
                                                return hitCount; /* callback wants to terminate search early */
                        }
                }
        }
        return hitCount;
}