/****************************************************************************
* MODULE:       R-Tree library 
*              
* AUTHOR(S):    Antonin Guttman - original code
*               Daniel Green (green@superliminal.com) - major clean-up
*                               and implementation of bounding spheres
*               
* PURPOSE:      Multidimensional index
*
* COPYRIGHT:    (C) 2001 by the GRASS Development Team
*
*               This program is free software under the GNU General Public
*               License (>=v2). Read the file COPYING that comes with GRASS
*               for details.
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include "assert.h"
#include "index.h"
#include "card.h"
#include "mfmalloc.h"

#define  ADDRESS 0
#define  ID      1

long  nodeCount;
int   maxLevel;
long  rootID;

struct Node *nodes;
struct Node *newNodes;

int RTreeContained(struct Rect *R, struct Rect *S);


/* Make a new index, empty.  Consists of a single node. */
struct Node * RTreeNewIndex(void)
{
	struct Node *x;

        nodeCount = 0;
        maxLevel  = 0;
	rootID    = 0;

	/* The tree traversal logic fails if there is    */
	/* "pointer" to node 0.  For real memory this    */
	/* cannot happen but for our memory mapped files */
	/* it can and does.  To avoid this, we will      */
	/* allocate a dummy node which will never be     */
	/* used as part of the tree.  A bit of a kludge  */
	/* but better than mucking around with index     */
	/* offsets all over the place.                   */

	x = RTreeNewNode();


	/* This is the real "first" node */

	x = RTreeNewNode();
	x->level = 0; /* leaf */
	return x;
}

int RTreeGetNodeCount()
{
   return(nodeCount);
}

int RTreeGetMaxLevel()
{
   return(maxLevel);
}

int RTreeGetRootID()
{
   return(rootID);
}


/*
 * 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))
				{
				   /*
				   printf("Internal node %ld (level %d) completely contained: shortcut\n",
				      (long)n->branch[i].child, n->level-1);

				   printf("DEBUG> contained: %9.6f %9.6f %9.6f %9.6f %9.6f %9.6f\n", 
				      (double)n->branch[i].rect.boundary[0],
				      (double)n->branch[i].rect.boundary[3],
				      (double)n->branch[i].rect.boundary[1],
				      (double)n->branch[i].rect.boundary[4],
				      (double)n->branch[i].rect.boundary[2],
				      (double)n->branch[i].rect.boundary[5]);
			
				   printf("DEBUG>        in: %9.6f %9.6f %9.6f %9.6f %9.6f %9.6f\n\n", 
				      (double)r->boundary[0],
				      (double)r->boundary[3],
				      (double)r->boundary[1],
				      (double)r->boundary[4],
				      (double)r->boundary[2],
				      (double)r->boundary[5]);
				   */

				   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;
}


int RTreeConvertToID(struct Node *N)
{
        register struct Node *n = N;
        register struct Node *child;
        register int i;
        int      index;

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

        index = n->id;

        for(i=0; i<MAXCARD; ++i)
        {
           if(n->level > 0 && n->branch[i].child)
           {
              child = n->branch[i].child;
              n->branch[i].child = (struct Node *)n->branch[i].child->id;
              RTreeConvertToID(child);
           }
        }

        return 0;
}

/*
 * JCG: Dump the parentage data for a specific item (input rectangle)
 */
int RTreeParentage(struct Node *N, int childID, int mode)
{
        register struct Node *n = N;
        register int i, count = 0;

	int index, status;

	++count;

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

	   n = &nodes[index];
        }

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

        if (n->level > 0) /* this is an internal node in the tree */
        {
                for (i=0; i<NODECARD; i++)
                {
                        if (n->branch[i].child)
                        {
                            status = RTreeParentage(n->branch[i].child, childID, mode);

			    if(status)
			    {
			       if(mode == ID)
				  printf("\nINTERNAL NODE %d (%ld) / CHILD %d\n", 
				     index, (long)n, i);
			       else
				  printf("\nINTERNAL NODE %ld / CHILD %d\n", (long)n, i);

			       printf("TRACE> level = %d\n", n->level);
			       printf("TRACE> count = %d\n", n->count);

			       printf("TRACE> branch[%d].child = %ld\n", i, (long)n->branch[i].child);
			       printf("TRACE> child x:  %13.10f  %13.10f\n",
				  n->branch[i].rect.boundary[0],
				  n->branch[i].rect.boundary[3]);

			       printf("TRACE> child y:  %13.10f  %13.10f\n",
				  n->branch[i].rect.boundary[1],
				  n->branch[i].rect.boundary[4]);

			       printf("TRACE> child z:  %13.10f  %13.10f\n",
				  n->branch[i].rect.boundary[2],
				  n->branch[i].rect.boundary[5]);

			       return 1;
			    }
                        }
                }
        }

        else /* this is a leaf node */
        {
                for (i=0; i<LEAFCARD; i++)
                {
                        if ((long)n->branch[i].child == (long)childID)
                        {
			   if(mode == ID)
			      printf("\nLEAF NODE %d (%ld) / CHILD %d\n", 
				 index, (long)n, i);
			   else
			      printf("\nLEAF NODE %ld / CHILD %d\n", (long)n, i);
			
			   printf("TRACE> level = %d\n", n->level);
			   printf("TRACE> count = %d\n", n->count);

                           printf("TRACE> branch[%d].child = %ld\n", i, (long)(n->branch[i].child));

			   printf("TRACE> x:  %13.10f  %13.10f\n",
			      n->branch[i].rect.boundary[0],
			       n->branch[i].rect.boundary[3]);

			   printf("TRACE> y:  %13.10f  %13.10f\n",
			      n->branch[i].rect.boundary[1],
			      n->branch[i].rect.boundary[4]);

			   printf("TRACE> z:  %13.10f  %13.10f\n",
			      n->branch[i].rect.boundary[2],
			      n->branch[i].rect.boundary[5]);

			   return 1;
                        }
                }
        }

        return 0;
}

/*
 * JCG: Dump all the nodes (tree order)
 */
int dumpCntr;

int RTreeDumpTree(struct Node *N, int dumpcount, int mode, int maxlev, int first)
{
        register struct Node *n = N;
        register int i, j, count = 0;

	int indent;

	char indentStr[1024];

	long index;

	if(first)
	   dumpCntr = 0;

	++dumpCntr;

	++count;

	if(dumpcount > 0 && count > dumpcount)
	   return 0;

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

	   n = &nodes[index];
        }

        assert(n->level >= 0);


	/* Create an "indent string" */

	indent = (maxlev - n->level) * 3;

	for(i=0; i<1024; ++i)
	   indentStr[i] = ' ';

        indentStr[indent] = '\0';



        if (n->level > 0) /* this is an internal node in the tree */
        {
		if(mode == ID)
		   printf("\n%s%d)  INTERNAL NODE (%ld -> %ld):\n", indentStr, dumpCntr, index, (long)n);
		else
		   printf("\n%s%d)  INTERNAL NODE (%ld):\n", indentStr, dumpCntr, (long)n);
	        
		fflush(stdout);

                printf("%sn->count = %d\n", indentStr, n->count);
		fflush(stdout);

                printf("%sn->level = %d\n", indentStr, n->level);
		fflush(stdout);

                for (i=0; i<NODECARD; i++)
                {
			if(mode == ID)
			   printf("\n%sINTERNAL NODE CHILDREN (%ld -> %ld) / CHILD %d:\n", indentStr, index, (long)n, i);
			else
			   printf("\n%sINTERNAL NODE CHILDREN (%ld) / CHILD %d:\n", indentStr, (long)n, i);

		        fflush(stdout);

                        if (n->branch[i].child)
                        {
                           printf("%sn->branch[%d].child = %ld\n", indentStr, i, (long)(n->branch[i].child));
		           fflush(stdout);

                           for (j=0; j<NUMSIDES; j++)
			   {
                              printf("%sn->branch[%d].rect.boundary[%d] = %13.10f\n",
                                 indentStr, i, j, n->branch[i].rect.boundary[j]);
		              fflush(stdout);
			   }

                            RTreeDumpTree(n->branch[i].child, dumpcount, mode, maxlev, 0);

		            if(dumpcount > 0 && count > dumpcount)
			       return 0;
                        }
                }
        }

        else /* this is a leaf node */
        {
		if(mode == ID)
		   printf("\n%s%d)  LEAF NODE (%ld -> %ld):\n", indentStr, dumpCntr, index, (long)n);
		else
		   printf("\n%s%d)  LEAF NODE (%ld):\n", indentStr, dumpCntr, (long)n);

	        fflush(stdout);

                printf("%sn->count = %d\n", indentStr, n->count);
	        fflush(stdout);

                printf("%sn->level = %d\n", indentStr, n->level);
	        fflush(stdout);

                for (i=0; i<LEAFCARD; i++)
                {
                        if (n->branch[i].child)
                        {
                           printf("%sn->branch[%d].child = %ld\n", indentStr, i, (long)(n->branch[i].child));
			   fflush(stdout);

                           for (j=0; j<NUMSIDES; j++)
			   {
                              printf("%sn->branch[%d].rect.boundary[%d] = %13.10f\n",
                                 indentStr, i, j, n->branch[i].rect.boundary[j]);
		              fflush(stdout);
			   }
                        }
                }
        }

        return 0;
}


/*
 * JCG: Traverse the tree depth first and write the nodes
 * (with modified addresses) to a new tree file
 */
long next;

int RTreeReorganize(struct Node *N, int maxlev, struct Node *M, int start)
{
   register struct Node *n = N;
   register struct Node *m = M;
   register int i, j;

   int count;
 
   int indent;
 
   int refdebug = 0;
 
   char indentStr[1024];
 
   long nindex;
   long mindex;
 
   if(start)
   {
      next     = 0;
      dumpCntr = 0;
   }
 
   ++dumpCntr;
 
   nindex = (long)N; n = &nodes   [nindex];
   mindex = (long)M; m = &newNodes[mindex];

   count = 0;
 
 
   /* Create an "indent string" */
 
   indent = (maxlev - n->level) * 3;
 
   for(i=0; i<1024; ++i)
      indentStr[i] = ' ';
 
   indentStr[indent] = '\0';
 
 
   // assert(n->level >= 0);
 
   if(refdebug)
   {
      printf("\n%s--> COPYING: n = %ld -> m = %ld (%ld -> %ld)\n",
 	indentStr, nindex, mindex, (long)n, (long)m);
      fflush(stdout);
   }
 
 
   if (n->level > 0) /* this is an internal node in the tree */
   {
      if(refdebug)
      {
 	printf("\n%s%d)  INTERNAL NODE %ld:\n", indentStr, dumpCntr, nindex);
 	fflush(stdout);
 
 	printf("%sn->count = %d\n", indentStr, n->count);
 	fflush(stdout);
 
 	printf("%sn->level = %d\n", indentStr, n->level);
 	fflush(stdout);
      }
 
      m->count = n->count;
      m->level = n->level;
 
      for (i=0; i<NODECARD; i++)
      {
 	if(refdebug)
 	{
 	   printf("\n%sINTERNAL NODE %ld / CHILD %d:\n", indentStr, nindex, i);
 	   fflush(stdout);
 	}
 
 	if (n->branch[i].child)
 	{
 	   if(refdebug)
 	   {
 	      printf("%sn->branch[%d].child = %ld\n", indentStr, i, (long)(n->branch[i].child));
 	      fflush(stdout);
 	   }
 
 	   ++next;
 
 	   m->branch[i].child = (struct Node *)next;
 
 	   for (j=0; j<NUMSIDES; j++)
 	   {
 	      if(refdebug)
 	      {
 		 printf("%sn->branch[%d].rect.boundary[%d] = %13.10f\n",
 		    indentStr, i, j, n->branch[i].rect.boundary[j]);
 		 fflush(stdout);
 	      }
 
 	      m->branch[i].rect.boundary[j] = n->branch[i].rect.boundary[j];
 	   }
 
 	   if(refdebug)
 	   {
 	      printf("\n%s--> SWITCHING: n -> %ld / m -> %ld\n", indentStr, (long)(n->branch[i].child), (long)(m->branch[i].child));
 	      fflush(stdout);
 	   }
 
 	    count += RTreeReorganize(n->branch[i].child, maxlev, m->branch[i].child, 0);
 	}
 	else
 	   m->branch[i].child = 0;
      }
   }
 
   else /* this is a leaf node */
   {
     if(refdebug)
     {
 	printf("\n%s%d)  LEAF NODE %ld:\n", indentStr, dumpCntr, nindex);
 	fflush(stdout);
 
 	printf("%sn->count = %d\n", indentStr, n->count);
 	fflush(stdout);
 
 	printf("%sn->level = %d\n", indentStr, n->level);
 	fflush(stdout);
      }
 
      m->count = n->count;
      m->level = n->level;
 
      for (i=0; i<LEAFCARD; i++)
      {
 	if (n->branch[i].child)
 	{
 	   if(refdebug)
 	   {
 	      printf("%sn->branch[%d].child = %ld\n", indentStr, i, (long)(n->branch[i].child));
 	      fflush(stdout);
 	   }
 
	   ++count;

 	   m->branch[i].child = n->branch[i].child;
 
 	   for (j=0; j<NUMSIDES; j++)
 	   {
 	      if(refdebug)
 	      {
 		 printf("%sn->branch[%d].rect.boundary[%d] = %13.10f\n",
 		    indentStr, i, j, n->branch[i].rect.boundary[j]);
 		 fflush(stdout);
 	      }
 
 	      m->branch[i].rect.boundary[j] = n->branch[i].rect.boundary[j];
 	  }
        }
        else
 	  m->branch[i].child = 0;
      }
   }
 
   return count;
}


/*
 * JCG: Dump all the nodes (memory order)
 */
int RTreeDumpMem(int count)
{
        register struct Node *n;
        register struct Node *base;
        register int i, j, k;

	base = (struct Node *)mfMemLoc();

	n = base;

	if(count == 0)
	   count = nodeCount;

	for(k=0; k<count; ++k)
	{
	   if (n->level > 0) /* this is an internal node in the tree */
	   {
		   printf("\nINTERNAL NODE %d->%ld (%ld:%ld):\n", k, (long)n,
		      (long)n - (long)base, ((long)n - (long)base) / sizeof(struct Node));

		   printf("DUMP> n->count = %d\n", n->count);
		   printf("DUMP> n->level = %d\n", n->level);

		   for (i=0; i<NODECARD; i++)
		   {
		           printf("\nINTERNAL NODE %ld / CHILD %d\n", (long)n, i);

			   if (n->branch[i].child)
			   {
			      printf("DUMP> n->branch[%d].child = %ld\n", i, (long)(n->branch[i].child));
			      for (j=0; j<NUMSIDES; j++)
				 printf("DUMP> n->branch[%d].rect.boundary[%d] = %13.10f\n",
				    i, j, n->branch[i].rect.boundary[j]);
			   }
		   }
	   }

	   else /* this is a leaf node */
	   {
		   printf("\nLEAF NODE %d->%ld (%ld:%ld):\n", k, (long)n,
		      (long)n - (long)base, ((long)n - (long)base) / sizeof(struct Node));
		   printf("DUMP> n->count = %d\n", n->count);
		   printf("DUMP> n->level = %d\n", n->level);

		   for (i=0; i<LEAFCARD; i++)
		   {
			   if (n->branch[i].child)
			   {
			      printf("DUMP> n->branch[%d].child = %ld\n", i, (long)(n->branch[i].child));
			      for (j=0; j<NUMSIDES; j++)
				 printf("DUMP> n->branch[%d].rect.boundary[%d] = %13.10f\n",
				    i, j, n->branch[i].rect.boundary[j]);
			   }
		   }
	   }

	   ++n;
	}

        return 0;
}

/*
 * Inserts a new data rectangle into the index structure.
 * Recursively descends tree, propagates splits back up.
 * Returns 0 if node was not split.  Old node updated.
 * If node was split, returns 1 and sets the pointer pointed to by
 * new_node to point to the new node.  Old node updated to become one of two.
 * 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,
		long tid, struct Node *n, struct Node **new_node, int level)
{
/*
	register struct Rect *r = R;
	register long tid = Tid;
	register struct Node *n = N, **new_node = New_node;
	register int level = Level;
*/

	register int i;
	struct Branch b;
	struct Node *n2;

	assert(r && n && new_node);
	assert(level >= 0 && level <= n->level);

	/* Still above level for insertion, go down tree recursively */
	if (n->level > level)
	{
		i = RTreePickBranch(r, n);
		if (!RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level))
		{
			/* child was not split */
			n->branch[i].rect =
				RTreeCombineRect(r,&(n->branch[i].rect));
			return 0;
		}
		else    /* child was split */
		{
			n->branch[i].rect = RTreeNodeCover(n->branch[i].child);
			b.child = n2;
			b.rect = RTreeNodeCover(n2);
			return RTreeAddBranch(&b, n, new_node);
		}
	}

	/* Have reached level for insertion. Add rect, split if necessary */
	else if (n->level == level)
	{
		b.rect = *r;
		b.child = (struct Node *) (tid);
		/* child field of leaves contains tid of data record */
		return RTreeAddBranch(&b, n, new_node);
	}
	else
	{
		/* Not supposed to happen */
		assert (FALSE);
		return 0;
	}
}

/* 
 * Insert a data rectangle into an index structure.
 * RTreeInsertRect provides for splitting the root;
 * returns 1 if root was split, 0 if it was not.
 * 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.
 * RTreeInsertRect2 does the recursion.
 */
int RTreeInsertRect(struct Rect *R, long Tid, struct Node **Root, int Level)
{
	register struct Rect *r = R;
	register long tid = Tid;
	register struct Node **root = Root;
	register int level = Level;
	register int i;
	register struct Node *newroot;
	struct Node *newnode;
	struct Branch b;
	int result;

	assert(r && root);
	assert(level >= 0 && level <= (*root)->level);
	for (i=0; i<NUMDIMS; i++) {
		assert(r->boundary[i] <= r->boundary[NUMDIMS+i]);
	}

	if (RTreeInsertRect2(r, tid, *root, &newnode, level))  /* root split */
	{
		newroot = RTreeNewNode();  /* grow a new root, & tree taller */
		newroot->level = (*root)->level + 1;

		rootID = newroot->id;

		if(newroot->level > maxLevel)
		   maxLevel = newroot->level;

		b.rect = RTreeNodeCover(*root);
		b.child = *root;
		RTreeAddBranch(&b, newroot, NULL);
		b.rect = RTreeNodeCover(newnode);
		b.child = newnode;
		RTreeAddBranch(&b, newroot, NULL);
		*root = newroot;
		result = 1;
	}
	else
		result = 0;

	return result;
}

/*
 * Allocate space for a node in the list used in DeletRect to
 * store Nodes that are too empty.
 */
static struct ListNode * RTreeNewListNode(void)
{
	return (struct ListNode *) mfMalloc(sizeof(struct ListNode));
	/* return new ListNode; */
}

static void RTreeFreeListNode(struct ListNode *p)
{
	mfFree(p);
	/* delete(p); */
}

/* 
 * Add a node to the reinsertion list.  All its branches will later
 * be reinserted into the index structure.
 */
static void RTreeReInsert(struct Node *n, struct ListNode **ee)
{
	register struct ListNode *l;

	l = RTreeNewListNode();
	l->node = n;
	l->next = *ee;
	*ee = l;
}

/*
 * 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;
	}
}

/*
 * Delete a data rectangle from an index structure.
 * Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
 * Returns 1 if record not found, 0 if success.
 * RTreeDeleteRect provides for eliminating the root.
 */
int RTreeDeleteRect(struct Rect *R, long Tid, struct Node**Nn)
{
	register struct Rect *r = R;
	register long tid = Tid;
	register struct Node **nn = Nn;
	register int i;
	struct Node *tmp_nptr = NULL;
	struct ListNode *reInsertList = NULL;
	register struct ListNode *e;

	assert(r && nn);
	assert(*nn);
	assert(tid >= 0);

	if (!RTreeDeleteRect2(r, tid, *nn, &reInsertList))
	{
		/* found and deleted a data item */

		/* reinsert any branches from eliminated nodes */
		while (reInsertList)
		{
			tmp_nptr = reInsertList->node;
			for (i = 0; i < MAXKIDS(tmp_nptr); i++)
			{
				if (tmp_nptr->branch[i].child)
				{
					RTreeInsertRect(
						&(tmp_nptr->branch[i].rect),
						(long)(tmp_nptr->branch[i].child),
						nn,
						tmp_nptr->level);
				}
			}
			e = reInsertList;
			reInsertList = reInsertList->next;
			RTreeFreeNode(e->node);
			RTreeFreeListNode(e);
		}
		
		/* check for redundant root (not leaf, 1 child) and eliminate */
		if ((*nn)->count == 1 && (*nn)->level > 0)
		{
			for (i = 0; i < NODECARD; i++)
			{
				tmp_nptr = (*nn)->branch[i].child;
				if(tmp_nptr)
					break;
			}
			assert(tmp_nptr);
			RTreeFreeNode(*nn);
			*nn = tmp_nptr;
		}
		return 0;
	}
	else
	{
		return 1;
	}
}

