/**********************************************************************
 
	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	<math.h>
#include	"utils.h"
#include	"xl2pdb_p.h"
#include	"memory_debug.h"


#define PM_PITCH	128
#define PM_MAX_NOS	700

double max_resolution,limit_resolution;
int lod_max,lod_min;
int lod_avg;
extern PDB_POLYGON2D * pdb_p_list;

extern int pdb_p_list_nos;
int polygon_cnt;
double data_input_resolution;

double max_reso;
PDB_PD_POINT ** half_plist;
int half_plist_len;
POINT_MATRIX * pm;
double pm_pitch;
int pm_no,pm_w,pm_h;
int del_cnt;
PDB_PD_POINT ** reso_point_list;
int rpl_len;


GB_RECT
get_pm_rect(GB_POINT p)
{
GB_RECT r;
GB_POINT s;
	s.x = 2;
	s.y = 2;
	r.tl = p_sub(p,s);
	r.br = p_add(p,s);
	return r;
}

GB_RECT test_r1,test_r2,test_r3;

void
set_test_point()
{
int target;
GB_POINT p1,p2,p3;
	p1.x = -109921.02;
	p1.y = -20825.12;
	test_r1 = get_pm_rect(p1);
}

int
test_point2(GB_POINT p)
{
	if ( inside_rect(&test_r1,p) ) {
		printf("---->\n");
	}
	return 0;
}

void
test_full_plist()
{
int i;
GB_POINT pt;
int target;
	for ( i = rpl_len-1 ; i >= 0 ; i -- ) {
		pt = reso_point_list[i]->p;
		target = 1;
		if ( inside_rect(&test_r1,pt) )
			goto ind;
		target = 2;
		if ( inside_rect(&test_r2,pt) )
			goto ind;
		target = 3;
		if ( inside_rect(&test_r3,pt) )
			goto ind;
		continue;
	ind:
		printf("%i %i %lf\n",
			i,target,
			reso_point_list[i]->reso);
	}
}

void
test_pm(char * str)
{
int x,y;
int cnt;
PDB_PD_POINT * pt;
	cnt = 0;
	for ( x = 0 ; x < pm_w ; x ++ )
		for ( y = 0 ; y < pm_h ; y ++ ) {
			pt = pm[x + pm_w*y].head;
			for ( ; pt ; pt = pt->line_next )
				cnt ++;
		}
	printf("test_pm (%s) = %i\n",str,cnt);
}

void
test_half_plist()
{
int i,j,k;
	if ( half_plist == 0 )
	return;
	for ( i = 1 ; i < half_plist_len ; i ++ ) {
		if ( half_plist[i] == 0 )
			continue;
		if ( half_plist[i]->lod_max != i )
			er_panic("test_half_plist(1)");
		j = i*2;
		k = j+1;
		if ( j >= half_plist_len )
			continue;
		if ( half_plist[i]->reso > half_plist[j]->reso )
			er_panic("test_half_plist(2)");
		if ( k >= half_plist_len )
			continue;
		if ( half_plist[i]->reso > half_plist[k]->reso )
			er_panic("test_half_plist(3)");
	}
}


void
insert_half_plist(PDB_PD_POINT * p)
{
int pod,pod1,pod2;
PDB_PD_POINT * p1;
extern int point_nos;
	
	if ( p->lod_max != -1 )
		er_panic("insert_half_plist(1)");
	if ( half_plist == 0 ) {
		half_plist = d_alloc(sizeof(PDB_PD_POINT*)*(point_nos+1),35);
		half_plist_len = 2;
		half_plist[0] = 0;
		half_plist[1] = p;
		p->lod_max = 1;
		return;
	}
	half_plist[half_plist_len] = p;
	pod2 = half_plist_len;
	half_plist[pod2]->lod_max = pod2;
	half_plist_len ++;
	for ( ; pod2 > 1 ; ) {
		pod = pod2/2;
		if ( half_plist[pod]->reso > half_plist[pod2]->reso ) {
			p1 = half_plist[pod2];
			half_plist[pod2] = half_plist[pod];
			half_plist[pod] = p1;

			half_plist[pod2]->lod_max = pod2;
			half_plist[pod]->lod_max = pod;
		}
		else 	break;
		pod2 = pod;
	}
}

void
delete_half_plist(PDB_PD_POINT * p)
{
int pod,pod1,pod2;
PDB_PD_POINT * p1;


	if ( p->lod_max == -1 )
		er_panic("delete_half_plist");
	if ( half_plist[p->lod_max] != p )
		er_panic("delete_half_plist(2)");
	if ( half_plist[half_plist_len-1] == p ) {
		p->lod_max = -1;
		half_plist_len --;
		if ( half_plist_len == 1 ) {
			d_f_ree(half_plist);
			half_plist = 0;
			half_plist_len = 0;
		}
		return;
	}
	pod2 = p->lod_max;
	p->lod_max = -1;
	for ( ; pod2 > 1 ; ) {
		pod = pod2/2;
		half_plist[pod2] = half_plist[pod];
		half_plist[pod2]->lod_max = pod2;
		pod2 = pod;
	}
	half_plist[1] = 0;

	pod = 1;
	half_plist_len --;
	half_plist[pod] = half_plist[half_plist_len];
	half_plist[pod]->lod_max = pod;
	for ( ; ; ) {
		pod1 = pod*2;
		pod2 = pod*2+1;
		if ( pod1 >= half_plist_len )
			break;
		if ( pod2 >= half_plist_len ) {
			if ( half_plist[pod1]->reso <
					half_plist[pod]->reso ) {
				goto exchange_pod1;
			}
			break;
		}
		if ( half_plist[pod]->reso
				< half_plist[pod1]->reso ) {
			if ( half_plist[pod2]->reso
					 < half_plist[pod]->reso ) {
				/* pod2 is smallest */
				goto exchange_pod2;
			}
			else {
				/* pod is smallest */
				/* finish */
				break;
			}
		}
		else {
			if ( half_plist[pod2]->reso
					< half_plist[pod1]->reso ) {
				/* pod2 is smallest */
				goto exchange_pod2;
			}
			else {
				/* pod1 is smallest */
				goto exchange_pod1;
			}
		}
	exchange_pod2:
		p1 = half_plist[pod];
		half_plist[pod] = half_plist[pod2];
		half_plist[pod2] = p1;
		half_plist[pod]->lod_max = pod;
		half_plist[pod2]->lod_max = pod2;
		pod = pod2;
		continue;
	exchange_pod1:
		p1 = half_plist[pod];
		half_plist[pod] = half_plist[pod1];
		half_plist[pod1] = p1;
		half_plist[pod]->lod_max = pod;
		half_plist[pod1]->lod_max = pod1;
		pod = pod1;
		continue;
	}

}

void
test_point(char * str)
{
PDB_POLYGON2D * p;
PDB_PD_POINT * ptr, * next,* prev;
	for ( p = pdb_p_list ; p ; p = p->next )
		for ( ptr = p->point ; ptr ; ptr = ptr->next ) {
			if ( ptr->lod_min == -1 )
				continue;
			next = ptr->line_next;
			prev = ptr->line_prev;
			if ( next ) {
				if ( next->line_prev != ptr )
					er_panic("test_point(2)");
			}
			if ( prev ) {
				if ( prev->line_next != ptr )
					er_panic("test_point(1)");
			}
		}
}

void
test_poly(PDB_POLYGON2D * pp,PDB_PD_POINT * ptr)
{
PDB_POLYGON2D * p;
PDB_PD_POINT * ppp;
	for ( p = pdb_p_list ; p ; p = p->next )
		if ( pp == p ) {
			for ( ppp = p->point ; ppp ; ppp = ppp->next )
				if ( ptr == ptr ) {
					printf("test poly ok\n");
					return;
				}
			printf("test poly ptr non exist\n");
		}
	printf("test poly non exist\n");
}

double
calc_resolution(
	GB_POINT p1,
	GB_POINT p2,
	GB_POINT p3)
{
GB_POINT q,p,r;
double d,len_p13,len_p12,len_p23;
double g1,g3;
double ret;
	q = p_sub(p2,p1);
	p = p_sub(p3,p1);
	r = p_sub(p2,p3);
	if ( p.x == 0 && p.y == 0 ) {
		d = sqrt(q.x*q.x + q.y*q.y);
	}
	else {
		d = (p.x*q.y - p.y*q.x)/sqrt(p.x*p.x + p.y*p.y);
	}
	if ( d < 0 )
		d = -d;
	len_p13 = p.x*p.x + p.y*p.y;
	len_p12 = q.x*q.x + q.y*q.y;
	len_p23 = r.x*r.x + r.y*r.y;

	if ( (g1=len_p12 - d*d) <= len_p13 &&
		(g3=len_p23 - d*d) <= len_p13 )
		return d;
	else if ( g1 < g3 )
		ret = sqrt(len_p12);
	else	ret = sqrt(len_p23);

	return ret;
}

void
calc_reso(PDB_PD_POINT * p)
{
	if ( p->line_prev == 0 && p->line_next == 0 ) {
		/* this point only line */
		/* not change the reso */
	}
	else if ( p->line_prev == 0 ) {
		if ( p->line_next->line_next == 0 )
			/* two points line */
			p->reso = distance(p->p,p->line_next->p);
		else 	p->reso = max_reso;
			/* more points line */
	}
	else if ( p->line_next == 0 ) {
		if ( p->line_prev->line_prev == 0 )
			/* two points line */
			p->reso = distance(p->p,p->line_prev->p);
		else	p->reso = max_reso;
			/* more points line */
	}
	else if ( p->line_next == p ) {
		/* one point loop */
		/* not change the reso */
	}
	else if ( p->line_next == p->line_prev ) {
		/* two points loop */
		p->reso = distance(p->p,p->line_prev->p);
	}
	else {
	double d1,d2;
		d1 = distance(p->p,p->line_prev->p);
		d2 = distance(p->p,p->line_next->p);
		if ( d1 < d2 )
			p->reso = d1;
		else	p->reso = d2;
	}
/*
	else 	p->reso = calc_resolution(
			p->line_prev->p,p->p,p->line_next->p);
*/
		/* others */

}



void
print_ptr(PDB_PD_POINT * ptr)
{
	for ( ; ptr ; ptr = ptr->next ) {
		ss_printf("\t(%f %f) - %i - %i\n",
			ptr->p.x,
			ptr->p.y,
			ptr->lod_min,
			ptr->lod_max);
	}
}

void
test_poly_ex(char * str,PDB_POLYGON2D * p)
{

if ( l_strcmp(p->name,l_string(std_cm,"L2110_49792")) == 0 ) {
goto prt;
}
if ( l_strcmp(p->subname,l_string(std_cm,"L2110_49792")) == 0 ) {
goto prt;
}
if ( l_strcmp(p->name,l_string(std_cm,"L2110_42054")) == 0 ) {
goto prt;
}
if ( l_strcmp(p->subname,l_string(std_cm,"L2110_42054")) == 0 ) {
goto prt;
}
if ( l_strcmp(p->subname,l_string(std_cm,"L2110_59450")) == 0 ) {
goto prt;
}
if ( l_strcmp(p->name,l_string(std_cm,"L2110_59450")) == 0 ) {
prt:
ss_printf("%s:- %ls(%ls) = %lf %lf\n",
str,
p->name,
p->subname,
p->point->p.x,
p->point->p.y);
print_ptr(p->point);
ss_printf("//\n");
}

}


void
polygon_lod_control_init(PDB_POLYGON2D * p)
{
PDB_PD_POINT * ptr1, * ptr2, * ptr3;


	if ( p->point == 0 )
		return;
	if ( p->point->next == 0 ) {

		p->point->line_next = p->point->line_prev = 0;
		return;
	}
	if ( p->point->next->next == 0 ) {
		if ( p->type == PDT_CLOSE ) {
			p->point->line_next = p->point->next;
			p->point->line_prev = p->point->next;
			p->point->next->line_next = p->point;
			p->point->next->line_prev = p->point;
		}
		else {
			p->point->line_next = p->point->next;
			p->point->line_prev = 0;
			p->point->next->line_next = 0;
			p->point->next->line_prev = p->point;
		}
		return;
	}
	ptr1 = p->point;
	ptr2 = ptr1->next;
	ptr3 = ptr2->next;

	ptr1->line_prev = 0;
	ptr1->line_next = ptr2;

	for ( ; ptr3 ; ) {
		ptr2->line_prev = ptr1;
		ptr2->line_next = ptr3;
		ptr1 = ptr2;
		ptr2 = ptr3;
		ptr3 = ptr3->next;
	}
	ptr2->line_prev = ptr1;
	if ( p->type == PDT_CLOSE ) {
		ptr2->line_next = p->point;
		p->point->line_prev = ptr2;
	}
	else {
		ptr2->line_next = 0;
	}
}


void
calc_moveto_reso(PDB_PD_POINT * a,PDB_PD_POINT * b)
{
PDB_PD_POINT * p1, * last, * start;
REAL1 reso,reso1;
int flag;
	if ( a == 0 )
		a = b;
	if ( a == 0 )
		return;
	if ( a->line_next == a )
		return;
	if ( a->line_prev == a )
		return;


	reso = 0;

	flag = 1;
	for ( p1 = a ; p1 ; p1 = p1->line_next ) {
/*
printf("fowrd %x %f\n",p1,p1->reso);
*/
		if ( flag == 0 && p1 == a )
			return;
		flag = 0;
		if ( p1->line_next == 0 )
			break;
		if ( p1->no & PP_LMOVE )
			break;
		if ( reso < p1->reso )
			reso = p1->reso;
	}
	last = p1;

	flag = 1;
	for ( p1 = a ; p1 ; p1 = p1->line_prev ) {
/*
printf("back %x %f\n",p1,p1->reso);
*/
		if ( flag == 0 && p1 == a )
			return;
		flag = 0;
		if ( p1->line_prev == 0 )
			break;
		if ( p1->line_prev->no & PP_LMOVE )
			break;
		if ( reso < p1->reso )
			reso = p1->reso;
	}
	start = p1;

	if ( reso == 0 )
		return;
	reso1 = distance(start->p,start->line_next->p);
	if ( reso < reso1 )
		reso = reso1;
	reso1 = distance(last->p,last->line_prev->p);
	if ( reso < reso1 )
		reso = reso1;

	reso = 1.01*reso;
	if ( start->reso != reso ) {
		delete_half_plist(start);
		start->reso = reso;
		insert_half_plist(start);
	}
	if ( last->reso != reso ) {
		delete_half_plist(last);
		last->reso = reso;
		insert_half_plist(last);
	}
}



void
set_max_resolution(PDB_POLYGON2D * p)
{
PDB_PD_POINT * ptr;
double d;
extern GB_RECT minrect;
double a,b;

int test;

	a = minrect.br.x - minrect.tl.x;
	b = minrect.br.y - minrect.tl.y;
	if ( a < b )
		max_reso = b * 2;
	else	max_reso = a * 2;


	for ( ptr = p->point ; ptr ; ptr = ptr->next ) {


		ptr->lod_max = -1;
		ptr->reso = 0;
		calc_reso(ptr);
		insert_half_plist(ptr);
		if ( max_resolution == -1 ) {
			if ( ptr->reso )
				max_resolution = ptr->reso;
		}
		else if ( ptr->reso ) {
			if ( max_resolution > ptr->reso )
				max_resolution = ptr->reso;
		}
	}

	for ( ptr = p->point ; ptr ; ptr = ptr->next ) {
		if ( (ptr->no & PP_LMOVE) ) {
			calc_moveto_reso(ptr->line_next,0);
			calc_moveto_reso(ptr->line_prev,0);
		}
		else if ( ptr->line_next == 0 )
			calc_moveto_reso(ptr,0);
		else if ( ptr->line_prev == 0 )
			calc_moveto_reso(ptr,0);
	}
	if ( max_resolution < limit_resolution )
		max_resolution = limit_resolution;
}

int
moveto_check(PDB_PD_POINT * p)
{
	if ( p->line_next == 0 && p->line_prev == 0 )
		return 0;
	if ( p->line_next == 0 || (p->no & PP_LMOVE) ) {
		if ( p->line_prev == 0 )
			er_panic("moveto_check(1)");
		if ( p->line_prev->no & PP_LMOVE )
			er_panic("moveto_check(2)");
		if ( p->line_prev->line_prev == 0 )
			return 2;
		if ( p->line_prev->line_prev->no & PP_LMOVE )
			return 2;
		er_panic("moveto_check(3)");
	}
	if ( p->line_prev == 0 ) {
		if ( p->line_next->line_next == 0 )
			return 1;
		if ( p->line_next->no & PP_LMOVE )
			return 1;
		er_panic("moveto_check(4)");
	}
	if ( p->line_prev->no & PP_LMOVE )
		return 1;
	return 0;
}

int
moveto_check2(PDB_PD_POINT * p)
{
	if ( p->line_next == 0 || (p->no & PP_LMOVE) )
		return 0;
	if ( p->line_prev == 0 )
		return 0;
	if ( p->line_prev->no & PP_LMOVE )
		return 0;
	return 1;
}

void
sort_resolution()
{
PDB_PD_POINT * ptr;
PDB_PD_POINT * prev, * next, * remove;
extern int point_nos;
int moveto_flag;
int count;

	VERIFY(point_nos)
	reso_point_list = d_alloc(sizeof(PDB_PD_POINT*)*point_nos,252);
	rpl_len = 0;
	memset(reso_point_list, 0, sizeof(PDB_PD_POINT*)*point_nos);
count = 0;
	for ( ; half_plist_len > 1 ; ) {

count ++;
if ( count > 1000 ) {
count = 0;
ss_printf("\t\tSORT RESO %i %i    \r",half_plist_len,rpl_len);
}
		ptr = half_plist[1];

		delete_half_plist(ptr);
		moveto_flag = 1;
		switch ( moveto_check(ptr) ) {
		case 0:
			prev = ptr->line_prev;
			next = ptr->line_next;
			break;
		case 1:
			remove = ptr->line_next;
			delete_half_plist(remove);
			prev = ptr->line_prev;
			next = remove->line_next;
			remove->lod_min = -1;
			remove->line_prev = remove->line_next = 0;
			reso_point_list[rpl_len++] = remove;
			moveto_flag = 0;
			break;
		case 2:

			remove = ptr->line_prev;
			delete_half_plist(remove);
			prev = remove->line_prev;
			next = ptr->line_next;
			remove->lod_min = -1;
			remove->line_prev = remove->line_next = 0;
			reso_point_list[rpl_len++] = remove;
			moveto_flag = 0;
			break;
		}
		if ( prev )
			prev->line_next = next;
		if ( next )
			next->line_prev = prev;

		ptr->lod_min = -1;
		ptr->line_prev = ptr->line_next = 0;
		if ( prev == ptr || next == ptr ) {
			if ( prev == ptr )
				prev = 0;
			if ( next == ptr )
				next = 0;
			goto end;
		}
		if ( prev && moveto_check2(prev) ) {
			delete_half_plist(prev);
			if ( prev->line_next == prev ) {
				prev->line_next = 0;
				prev->line_prev = 0;
			}
			calc_reso(prev);
			insert_half_plist(prev);
		}
		if ( next && prev != next && moveto_check2(next) ) {
			delete_half_plist(next);
			calc_reso(next);
			insert_half_plist(next);
		}
	end:
		reso_point_list[rpl_len++] = ptr;

		if ( moveto_flag )
			calc_moveto_reso(prev,next);

	}
	if ( half_plist ) {
		d_f_ree(half_plist);
		half_plist_len = 0;
	}
}

void
pm_regulation()
{
int st_x,st_y,x,y;
int w,h;
	w = pm_w;
	h = pm_h;
	for ( st_x = 0 , st_y = 0 ; st_x < w && st_y < h ; ) {
		x = st_x;
		for ( ; x < w ; x ++ ) {
			if ( pm[x + pm_w*st_y].head ) {
				w = x+1;
				break;
			}
			pm[x + pm_w*st_y].rate = 0;
		}
		y = st_y;
		for ( ; y < h ; y ++ ) {
			if ( pm[st_x + pm_w*y].head ) {
				h = y+1;
				break;
			}
			pm[st_x + pm_w*y].rate = 0;
		}
		st_x ++;
		st_y ++;
	}
	w = 0;
	h = pm_h;
	for ( st_x = pm_w-1 , st_y = 0 ; st_x >= w && st_y < h ; ) {
		x = st_x;
		for ( ; x >= w ; x -- ) {
			if ( pm[x + pm_w*st_y].head ) {
				w = x;
				break;
			}
			pm[x + pm_w*st_y].rate = 0;
		}
		y = st_y;
		for ( ; y < h ; y ++ ) {
			if ( pm[st_x + pm_w*y].head ) {
				h = y+1;
				break;
			}
			pm[st_x + pm_w*y].rate = 0;
		}
		st_x --;
		st_y ++;
	}

	w = pm_w;
	h = 0;
	for ( st_x = 0 , st_y = pm_h-1 ; st_x < w && st_y >= h ; ) {
		x = st_x;
		for ( ; x < w ; x ++ ) {
			if ( pm[x + pm_w*st_y].head ) {
				w = x+1;
				break;
			}
			pm[x + pm_w*st_y].rate = 0;
		}
		y = st_y;
		for ( ; y >= h ; y -- ) {
			if ( pm[st_x + pm_w*y].head ) {
				h = y;
				break;
			}
			pm[st_x + pm_w*y].rate = 0;
		}
		st_x ++;
		st_y --;
	}
	w = 0;
	h = 0;
	for ( st_x = pm_w-1 , st_y = pm_h-1 ; st_x >= w && st_y >= h ; ) {
		x = st_x;
		for ( ; x >= w ; x -- ) {
			if ( pm[x + pm_w*st_y].head ) {
				w = x;
				break;
			}
			pm[x + pm_w*st_y].rate = 0;
		}
		y = st_y;
		for ( ; y >= h ; y -- ) {
			if ( pm[st_x + pm_w*y].head ) {
				h = y;
				break;
			}
			pm[st_x + pm_w*y].rate = 0;
		}
		st_x --;
		st_y --;
	}
}


void
set_lod(int x,int y,int lod,double reso)
{
PDB_PD_POINT * p;
POINT_MATRIX * pmp;
int cnt;
int max;

	pmp = &pm[x + pm_w*y];


	max = PM_MAX_NOS*pmp->rate;
	if ( max < 10 )
		max = 10;
	cnt = 0;
	for ( ; pmp->head ; ) {

		if ( cnt >= max ) {
			break;
		}

		p = pmp->head;
		if ( p->reso >= reso )
			break;
		del_cnt ++;
		pmp->head = p->line_next;
		p->lod_max = lod;
		p->lod_min = 0;
		if ( lod_max < lod )
			lod_max = lod;
		cnt ++;
	}
}

void
marge_lod(int x,int y,int pitch)
{
POINT_MATRIX * pmp[4];
PDB_PD_POINT ** pp1, * p1;
int i;

	pmp[0] = &pm[x + pm_w*y];
	if ( x + pitch < pm_w )
		pmp[1] = &pm[x + pitch + pm_w*y];
	else	pmp[1] = 0;
	if ( y + pitch < pm_h )
		pmp[2] = &pm[x + pm_w*(y+pitch)];
	else	pmp[2] = 0;
	if ( pmp[1] && pmp[2] )
		pmp[3] = &pm[x + pitch + pm_w*(y+pitch)];
	else	pmp[3] = 0;
	for ( i = 1 ; i < 4 ; i ++ ) {
		if ( pmp[i] == 0 )
			continue;
		pp1 = &pmp[0]->head;
		for ( ; pmp[i]->head ; ) {
			p1 = pmp[i]->head;
			pmp[i]->head = p1->line_next;
			for ( ; *pp1 && (*pp1)->lod_max < p1->lod_max ;
				pp1 = &(*pp1)->line_next );
			p1->line_next = *pp1;
			*pp1 = p1;
			pp1 = &p1->line_next;
		}
		pmp[0]->rate += pmp[i]->rate;
		pmp[i]->head = 0;
	}
	pmp[0]->rate = pmp[0]->rate/4;
}



void
set_polygon_lod()
{
PDB_POLYGON2D * p;
PDB_PD_POINT * ptr;


	for ( p = pdb_p_list ; p ; p = p->next ) {
		p->lod_max = 0;
		p->lod_min = 0;
		p->minrect.tl.x = p->minrect.tl.y = 0;
		p->minrect.br.x = p->minrect.br.y = -1;

		for ( ptr = p->point ; ptr ; ptr = ptr->next ) {

			if ( ptr->lod_min == -1 )
				ptr->lod_max = lod_max;
			if ( ptr->lod_max > p->lod_max )
				p->lod_max = ptr->lod_max;

			insert_rect(&p->minrect,ptr->p);
		}
	}
}

void
set_point_lod()
{
PDB_POLYGON2D * p;
PDB_PD_POINT * ptr;
double * reso;
int i,st,lod,j;
#define LOD_MAX	30
double min,max,r;


	reso = malloc(sizeof(double)*LOD_MAX);
	max = -1;
	for ( i = 0 ; i < rpl_len ; i ++ ) {
		ptr = reso_point_list[i];
		if ( max < 0 || max < ptr->reso )
			max = ptr->reso;
	}
	reso[LOD_MAX-1] = max*1.1;
	min = 0;
	for ( i = 0 ; i < rpl_len ; i ++ ) {
		if ( reso_point_list[i]->reso
				<= 0.1*data_input_resolution ) {
			reso_point_list[i]->reso = 0;
			reso_point_list[i] = 0;
		}
		else {
			min = reso_point_list[i]->reso;
			break;
		}
	}
	if ( i == rpl_len )
		goto end;
	for ( i = LOD_MAX-2 ; i >= 0 ; i -- )
		reso[i] = reso[i+1]/2;
	for ( st = 0 ; st < LOD_MAX ; st ++ )
		if ( reso[st] > min )
			break;
	lod = 0;
	for ( i = 0 ; i < rpl_len ; i ++ ) {
		ptr = reso_point_list[i];
		if ( ptr == 0 )
			continue;
		r = ptr->reso;
		for ( j = st ; j < LOD_MAX ; j ++ )
			if ( r < reso[j] )
				break;
		if ( lod < j - st )
			lod = j - st;
		ptr->lod_min = 0;
		ptr->lod_max = lod;

		if ( lod_max < lod )
			lod_max = lod;
	}
	max_resolution = reso[st]/2;
end:
	free(reso);
}

void
point_thin_out()
{
int lod[LOD_MAX];
int i;
PDB_PD_POINT * ptr, ** pp;
PDB_POLYGON2D * pol;
int no;


	for ( pol = pdb_p_list ; pol ; pol = pol->next ) {
		no = 0;
		for ( pp = &pol->point ; *pp ; ) {
			ptr = *pp;
			if ( ptr->reso == 0 ) {
				*pp = ptr->next;
				d_f_ree(ptr);
				continue;
			}
			else {
				ptr->no = no|(ptr->no&PP_LFLAGS);
				no ++;
				pp = &ptr->next;
			}
		}
	}
}


void
lod_control()
{
PDB_POLYGON2D * p;
extern int point_nos;
double rr;


	limit_resolution = 0.1;
	ss_printf("\tINIT...\n");
	for ( p = pdb_p_list ; p ; p = p->next )
		polygon_lod_control_init(p);
	max_resolution = -1;
	ss_printf("\tRESOLUTION SET...\n");
	for ( p = pdb_p_list ; p ; p = p->next ){
		PDB_PD_POINT *ppoint;
	}
	for ( p = pdb_p_list ; p ; p = p->next )
		set_max_resolution(p);
	ss_printf("\tLOD START...\n");
	ss_printf("\t\tSORT...\n");
	sort_resolution();
	ss_printf("\n");

	ss_printf("SET LOD\n");
	set_point_lod();

	point_thin_out();


	ss_printf("POLYGON LOD\n");
	set_polygon_lod();
}
