/**********************************************************************
 
	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 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 = 1;
	s.y = 1;
	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 = -118364.88;
	p1.y = -25605.95;
	p2.x = -118364.82;
	p2.y = -25601.86;
	p3.x = -118362.9;
	p3.y = -25606.1;
	test_r1 = get_pm_rect(p1);
	test_r2 = get_pm_rect(p2);
	test_r3 = get_pm_rect(p3);
}

int
test_point2(GB_POINT p)
{
	if ( inside_rect(&test_r1,p) )
		return 1;
	if ( inside_rect(&test_r2,p) )
		return 2;
	if ( inside_rect(&test_r3,p) )
		return 3;
	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;
	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 )
		return sqrt(len_p12);
	else	return sqrt(len_p23);
}

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 	p->reso = calc_resolution(
			p->line_prev->p,p->p,p->line_next->p);
		/* others */
/*
if ( test_point2(p->p) ) {
printf("reso\n");
if ( p->line_prev )
printf("\t(%f %f) %i\n",p->line_prev->p.x,p->line_prev->p.y,p->line_prev->no);
printf("\t(%f %f) %i\n",p->p.x,p->p.y,p->no);
if ( p->line_next )
printf("\t(%f %f) %i\n",p->line_next->p.x,p->line_next->p.y,p->line_next->no);
printf("\t");
if ( p->line_prev )
printf("%lf ",distance(p->p,p->line_prev->p));
else printf("* ");
if ( p->line_next )
printf("%lf ",distance(p->p,p->line_next->p));
else printf("* ");
if ( p->line_next && p->line_prev )
printf("%lf ",distance(p->line_prev->p,p->line_next->p));
else printf("* ");
printf("\n\t- %lf\n",p->reso);
}
*/
}

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
set_max_resolution(PDB_POLYGON2D * p)
{
PDB_PD_POINT * ptr;
double d;
extern GB_RECT minrect;
double a,b;
	a = minrect.br.x - minrect.tl.x;
	b = minrect.br.y - minrect.br.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;
		}
	}
	if ( max_resolution < limit_resolution )
		max_resolution = limit_resolution;
}

void
insert_pm(PDB_PD_POINT * ptr)
{
int x,y;
POINT_MATRIX * pmp;
extern GB_RECT minrect;


	ptr->lod_max = pm_no ++;
	x = floor((ptr->p.x - minrect.tl.x)/pm_pitch);
	y = floor((ptr->p.y - minrect.tl.y)/pm_pitch);
//	printf("x:%d y:%d pm_w:%d pm_h:%d ptr->p.x:%f ptr->p.y:%f\n",
//		x,y, pm_w, pm_h, ptr->p.x, ptr->p.y);
	VERIFY_PT_IS_NOT_ZERO(ptr->p)
	if ( x >= pm_w || y >= pm_h || x < 0 || y < 0 )
		er_panic("insert_pm");

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


	ptr->line_next = 0;
	if ( pmp->head == 0 ) {
		pmp->head = pmp->tail = ptr;
	}
	else {
		pmp->tail->line_next = ptr;
		pmp->tail = ptr;
	}

}

void
init_pm()
{
int i,x,y;
double len_y,len_x;
double delta1,delta2;
extern GB_RECT minrect;
	if ( pm )
		d_f_ree(pm);
	pm_no = 0;
	pm_pitch = PM_PITCH * max_resolution;
	pm_w = ceil((len_x = minrect.br.x - minrect.tl.x)/pm_pitch);
	pm_h = ceil((len_y = minrect.br.y - minrect.tl.y)/pm_pitch);
	pm = d_alloc(sizeof(POINT_MATRIX)*pm_w*pm_h,14);
	for ( i = 0 ; i < pm_w*pm_h ; i ++ ) {
		pm[i].head = pm[i].tail = 0;
		pm[i].rate = 1;
	}
	delta1 = (len_y - (pm_h-1)*pm_pitch)/pm_pitch;
	for ( i = 0 ; i < pm_w-1 ; i ++ )
		pm[i + pm_w*(pm_h-1)].rate = delta1;
	delta2 = (len_x - (pm_w-1)*pm_pitch)/pm_pitch;
	for ( i = 0 ; i < pm_h-1 ; i ++ )
		pm[pm_w-1 + pm_w*i].rate = delta2;
	pm[pm_w-1 + pm_w*(pm_h-1)].rate = delta1*delta2;

	for ( i = 0 ; i < rpl_len ; i ++ ){
		VERIFY_PT_IS_NOT_ZERO(reso_point_list[i]->p)
		insert_pm(reso_point_list[i]);
	}
}


void
sort_resolution()
{
PDB_PD_POINT * ptr;
PDB_PD_POINT * prev, * next;
extern int point_nos;
	VERIFY(point_nos)
	reso_point_list = d_alloc(sizeof(PDB_PD_POINT*)*point_nos,252);
	rpl_len = 0;
	/*{
		int i=0;
		for(;i<point_nos;++i)
			memset(reso_point_list[i]->p, 1, reso_point_list);
	}*/
	memset(reso_point_list, 0, sizeof(PDB_PD_POINT*)*point_nos);
	for ( ; half_plist_len > 1 ; ) {
		ptr = half_plist[1];
		VERIFY_PT_IS_NOT_ZERO(ptr->p)
		delete_half_plist(ptr);
		prev = ptr->line_prev;
		next = ptr->line_next;
		ptr->lod_min = -1;
		ptr->line_prev = ptr->line_next = 0;
		if ( prev == ptr || next == ptr )
			goto end;
		if ( prev )
			prev->line_next = next;
		if ( next )
			next->line_prev = prev;
		if ( 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 ) {
			delete_half_plist(next);
			calc_reso(next);
			insert_half_plist(next);
		}
	end:
		VERIFY_PT_IS_NOT_ZERO(ptr->p)
		reso_point_list[rpl_len++] = ptr;
		if(reso_point_list[991]){
			VERIFY_PT_IS_NOT_ZERO(reso_point_list[991]->p)
		}
	}
	if ( half_plist ) {
		d_f_ree(half_plist);
		half_plist_len = 0;
	}
	{
		int i;
		for(i=0;i<rpl_len;++i){
			VERIFY_PT_IS_NOT_ZERO(reso_point_list[i]->p)
		}
	}
}

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

int
pm_marge(double rr_start)
{
int pitch,x,y;
double reso;
int lod;
double reso_rate;
	del_cnt = 0;
	lod_max = 0;
	lod_min = 0;
	pitch = 1;
	reso_rate = rr_start;
	reso = max_resolution*reso_rate;
	lod = 0;
	for ( ; lod < 21 ; ) {
		printf("\t\t%i/%i\r",del_cnt,pm_no);
		fflush(stdout);
		if ( pitch >= pm_w && pitch >= pm_h &&
				pm[0].head == 0 ) {
			printf("\n");
			return 0;
		}
		for ( x = 0 ; x < pm_w ; x += pitch )
			for ( y = 0 ; y < pm_h ; y += pitch )
				set_lod(x,y,lod,reso);
		for ( x = 0 ; x < pm_w ; x += 2*pitch )
			for ( y = 0 ; y < pm_h ; y += 2*pitch )
				marge_lod(x,y,pitch);
		lod ++;
		reso_rate = (rr_start*(20-lod) + 2*lod)/20;
		reso *= reso_rate;
		pitch *= 2;
	}
	printf("\n");
	return -1;
}

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;
		for ( ptr = p->point ; ptr ; ptr = ptr->next ) {
			if ( ptr->lod_max > p->lod_max )
				p->lod_max = ptr->lod_max;
		}
	}
}


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

	limit_resolution = 0.1;
	printf("\tINIT...\n");
	for ( p = pdb_p_list ; p ; p = p->next )
		polygon_lod_control_init(p);
	max_resolution = -1;
	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);
	printf("\tLOD START...\n");
	printf("\t\tSORT...\n");
	sort_resolution();
	{
		int i;
		for ( i = 0 ; i < rpl_len ; i ++ ){
			VERIFY_PT_IS_NOT_ZERO(reso_point_list[i]->p)
		}
	}
	for ( rr = 2 ; rr < 5 ; rr += 0.1 ) {
		printf("\t\tRESO RATE = %lf\n",rr);
		init_pm();
		printf("\t\tREGULATION...\n");
		pm_regulation();
		printf("\t\tMARGE...\n");
		if ( pm_marge(rr) == 0 )
			goto next;
	}
	printf("CANNOT FINISH LOD CONTROL\n");
next:
	printf("POLYGON LOD\n");
	set_polygon_lod();
}
