/* Octree.c: trees with N children per node */

#include "Octree.h"
#include "Memory.h"
#include "debug.h"
#include "error.h"

#ifdef BETTER_MEMMAN
static STORAGE *octreeStor = (STORAGE *)NULL;
#define NEWOCTREENODE()  	(OCTREE *)New(sizeof(OCTREE), &octreeStor)
#define DISPOSEOCTREENODE(ptr) Dispose((unsigned char *)(ptr), &octreeStor)
#else /*BETTER_MEMMAN*/
#define NEWOCTREENODE()	(OCTREE *)Alloc(sizeof(OCTREE))
#define DISPOSEOCTREENODE(ptr) Free((char *)ptr, sizeof(OCTREE))
#endif /*BETTER_MEMMAN*/

OCTREE *NewOctreeNode(void *pelement)
{
	OCTREE *nt;
	int i;

	nt = NEWOCTREENODE();
	nt->pelement = pelement;
	for (i=0; i<8; i++)
		nt->child[i] = (void *)NULL;

	return nt;
}

OCTREE *OctreeAdd(OCTREE *octree, 
		void *pelement, 
		int (*nodecmp)(void *pelem1, void *pelem2))
{
	OCTREE *o, *p;
	int cmp=0;

	o = (OCTREE *)NULL;
	p = octree;
	while (p) {
		cmp = nodecmp(p->pelement, pelement);
		if (cmp > 0) {
			o = p;
			p = p->child[cmp-1];
		} else	/* node is already in the octree */
			return octree;
	}

/* p is null, o is the octree node where we should add the new child */	
	p = NewOctreeNode(pelement);

	if (o) {		/* add the new node to the old octree */
		o->child[cmp-1] = p;
		return octree;
	} else 
		return p;	/* new octree */
}

void *OctreeFind(OCTREE *octree, 
		 void *pelement, 
		 int (*nodecmp)(void *pelem1, void *pelem2))
{
	OCTREE *p;
	int cmp;

	p = octree;
	while (p) {
		cmp = nodecmp(p->pelement, pelement);
		if (cmp == 0)
			return p->pelement;
		else 
			p = p->child[cmp-1];
	}

	return (void *)NULL;
}

void OctreeIterate(OCTREE *octree, void (*func)(void *pelem))
{
	int i;

	if (octree) {
		for (i=0; i<8; i++)
			OctreeIterate(octree->child[i], func);
		func(octree->pelement);
	}
}

void OctreeDestroy(OCTREE *octree)
{
	int i;

	if (octree) {
		for (i=0; i<8; i++)
			OctreeDestroy(octree->child[i]);
		DISPOSEOCTREENODE(octree);
	}
}



