/**********************************************************************
 
	Copyright (C) 2003 Hirohisa MORI <joshua@nichibun.ac.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/


#include	"memory_debug.h"
#include	"xl2pdb_p.h"

extern PDB_POLYGON2D * pdb_p_list;
PDB_LOD_PT * pdb_lpt;
extern int pdb_p_list_nos;

PDB_PT *
make_pt(PDB_POLYGON2D * p)
{
GB_RECT r;
int max,min;
int cnt;
PDB_POLYGON2D * p1;
PDB_PT * pt;
int i;
int index;
int prev_index;
int f;
	if ( p == 0 )
		return 0;
	r = p->minrect;
	max = p->lod_max;
	min = p->lod_min;
	cnt = 1;
	for ( p1 = p->next ; p1 ; p1 = p1->next ) {
		r.tl.x += p1->minrect.tl.x;
		r.tl.y += p1->minrect.tl.y;
		r.br.x += p1->minrect.br.x;
		r.br.y += p1->minrect.br.y;
		max += p1->lod_max;
		min += p1->lod_min;
		cnt ++;
	}
	r.tl.x = r.tl.x/cnt;
	r.tl.y = r.tl.y/cnt;
	r.br.x = r.br.x/cnt;
	r.br.y = r.br.y/cnt;
	max = max/cnt;
	min = min/cnt;

	pt = d_alloc(sizeof(*pt));
	pt->r = r;
	pt->lod_max = max;
	pt->lod_min = min;
	for ( i = 0 ; i < PTR_MAX ; i ++ ) {
		pt->next[i].type = 0;
		pt->next[i].ptr.pt = 0;
	}

	prev_index = -1;
	f = 1;
	for ( ; p ; ) {
		p1 = p;
		p = p->next;
		index = 0;
		if ( p1->minrect.tl.x >= r.tl.x )
			index |= TLX_L;
		if ( p1->minrect.tl.y >= r.tl.y )
			index |= TLY_L;
		if ( p1->minrect.br.x >= r.br.x )
			index |= BRX_L;
		if ( p1->minrect.br.y >= r.br.y )
			index |= BRY_L;
		pt->next[index].type = PTT_POLYGON2D;
		p1->next = pt->next[index].ptr.poly;
		pt->next[index].ptr.poly = p1;
		if ( prev_index != -1 ) {
			if ( index != prev_index )
				f = 0;
		}
		prev_index = index;
	}
	if ( f ) {
		if ( cnt >= PTR_MAX/2 ){
			fprintf(stderr,"same index\n");
			exit(1);
		}
		pt->same_index = 1;
	}
	else	pt->same_index = 0;
	return pt;
}

void
trace_tree(PDB_PT * p)
{
int i;
	if ( p == 0 )
		return;
	if ( p->same_index )
		return;
	for ( i = 0 ; i < PTR_MAX ; i ++ ) {
		switch ( p->next[i].type ) {
		case 0:
			continue;
		case PTT_POLYGON2D:
			if ( p->next[i].ptr.poly->next ) {
				p->next[i].ptr.pt = make_pt(
					p->next[i].ptr.poly);
				if ( p->next[i].ptr.pt ) {
					p->next[i].type = PTT_PT;
					trace_tree(p->next[i].ptr.pt);
				}
				else {
					p->next[i].type = 0;
				}
			}
			break;
		case PTT_PT:
			trace_tree(p->next[i].ptr.pt);
			break;
		}
	}
}


PDB_LOD_PT *
divide_lod(PDB_POLYGON2D * p)
{
PDB_LOD_PT * ret;
int lod;
PDB_POLYGON2D * p1, * p2;
PDB_PD_POINT ** pp,* pt1;
	ret = d_alloc(sizeof(*ret));
	ret->max = 0;
	for ( lod = 0 ; lod < 32 ; lod ++ ) {
		ret->next[lod].type = 0;
		ret->next[lod].ptr.poly = 0;
	}
	for ( ; p ; ) {
		p1 = p->next;
		for ( lod = 0 ; lod < 32 ; lod ++ ) {
			if ( lod < p->lod_min ||
					lod > p->lod_max )
				continue;
			p2 = d_alloc(sizeof(*p));
			memcpy(p2,p,sizeof(*p));
			p2->point = 0;
			for ( pp = &p->point ; *pp ; ) {
				pt1 = *pp;
				if ( pt1->lod_max == lod ) {
					*pp = (*pp)->next;
					pt1->next = p2->point;
					p2->point = pt1;
				}
				else {
					pp = &(*pp)->next;
				}
			}
			if ( p2->point ) {
				p2->next = ret->next[lod].ptr.poly;
				ret->next[lod].ptr.poly = p2;
				ret->next[lod].type = PTT_POLYGON2D;
				if ( ret->max < lod + 1 )
					ret->max = lod+1;
			}
			else {
				d_f_ree(p2);
			}
		}
		d_f_ree(p);
		p = p1;
	}
	return ret;
}



void
make_tree()
{
int i;
	pdb_lpt = divide_lod(pdb_p_list);
	for ( i = 0 ; i < pdb_lpt->max ; i ++ ) {
		pdb_lpt->next[i].ptr.pt = make_pt(
			pdb_lpt->next[i].ptr.poly);
		pdb_lpt->next[i].type = PTT_PT;
		trace_tree(pdb_lpt->next[i].ptr.pt);
	}
}
