/*
	dlg2raw.c

	d2r.bat = cl /AL dlg2raw.c utm 

	Converts the optional format 1:100,000 DLG to raw files.

Example 'CTL' files

'HY.CTL':

Hydrography -- HY = 7

	hym = 0
	shr = 3
		200
		201
		203
	lmt = 1
		204
	str = 3
		412
		413
		610
	cnl = 1
		414
	chn = 1
		419
	bks = 2
		605
		606

Transportation (Trails, Roads and Highways)-- 'RD.CTL':

 rd = 6
	rmc = 0
	rd1 = 4
		201
		202
		203
		204
	rd2 = 5
		205
		206
		207
		208
		214	
	rd3 = 3
		209
		217
		218
	rd4 = 1
		210
	rd5 = 3
		211
		212
		213

Rail Road -- 'RR.CTL':

 RR = 2
	rrm = 0
	rr = 7
		201
		202
		204
		205
		207
		209
		210

Miscellaneous Transportation -- 'MT.CTL':

 MT = 5
	mtm = 0
	apt = 5
		300
		403
		404
		405
		407
	pip = 1
		201
	pow = 1
		202
	tel = 1
		203

	

*/

#include <stdio.h>
#include <string.h>
#include <math.h>

#define NUM_TYPE 4
#define MAX_FILES 10
#define MAX_PTS 8192
#define MAX_BND 1
#define S_SIZE 40

char Cr=0xd;
int File[1000];
long Attrib1[NUM_TYPE]={  170,50,180,190  };
char FileName[MAX_FILES][20];
int Assn[1000];
FILE *Fp[MAX_FILES];
long FSize[MAX_FILES];
int FNum[MAX_FILES];
char FName[MAX_FILES][100];
char InFile[1000][15];

int P;
struct types
{
	char id[5],*name;
}Type[NUM_TYPE]=
{
	{"RD","Roads"},
	{"HY","Hydrology"},
	{"RR","Railroads"},
	{"MT","Miscellaneous Transportation"}
};
char StateId[10];
double X[MAX_PTS],Y[MAX_PTS];
long Size=0;
FILE *FpOut;
long Atr1[1000],Atr2[1000],TAtr1[1000],TAtr2[1000];
char check_char(char c);

main()
{
	int i,j,k;
	char string[100],ans,filename[100],outfile[100];
	int num,numfile;
	int split=0;
	FILE *fp;
	char str1[100],str2[100];
	int misses=0;
	double lat,lon;

	printf("Give 2 letter state id, e.g. Virginia = VA\n\n");
	scanf("%s",StateId);
	FpOut=fopen("dlg2raw.out","at");
	if(!FpOut)
	{
		printf("Could not open 'dlg2raw.out' to append.\n\n");
		exit(0);
	}
	P=7;		/* choice '8' for US -- Clark 1866 */
	do
	{
		for(i=0;i<NUM_TYPE;i++)
			printf("%4d -- %s\n",i+1,Type[i].name);
		printf("\n   x -- exit program\n");
		ans=getch();
		num=ans-'1';
		if(ans!='x')
		{
			if(num<0||num>=NUM_TYPE)
			{
				printf("\n\n  %c is an invalid answer.\n\n",ans);
			}
			else
			{
				split=set_files(num);
				fp=fopen("15min.txt","rt");
				if(!fp)
				{
					printf("Could not find '15min.txt' file listing quads.\n");
					exit(0);
				}
				numfile=0;
				while(fgets(string,99,fp))
				{
					sscanf(string,"%s%s%lf%lf",str1,str2,&lat,&lon);
					if(strlen(str1)>0&&strlen(str2)>0)
					{
						sprintf(InFile[numfile],"%s%s%s.",str1,Type[num].id,str2);
						printf("%3d '%s'\n",numfile+1,InFile[numfile]);
						numfile+=1;
					}
				}
				if(fp)
					fclose(fp);
				printf("Checking files:\n");
				for(i=0;i<numfile;i++)
				{
					printf("%c%d of %d",Cr,i+1,numfile);
					fp=fopen(InFile[i],"rt");
					if(!fp)
					{
						printf("Could not open '%s' %10.5lf %10.5lf\n",
							InFile[i],lat,lon);
						misses+=1;
					}
					if(fp)
						fclose(fp);
				}
				if(numfile>=0)
				{
					strcpy(filename,InFile[0]);
					printf("Working '%s'\n",filename);
					fprintf(FpOut,"Working '%s'\n",filename);
					strcpy(string,filename);
					string[5]='\0';
					sprintf(outfile,"%s%sm.raw",StateId,Type[num].id);
					fprintf(FpOut,"output file = '%s'\n",outfile);
					if(split<=0)
					{
						makeraw(filename,outfile,"wt");
					}
					else if(splitraw(filename,num)==-5)
					{
						numfile=0;
						ans='x';
					}
					for(i=1;i<numfile;i++)
					{
						strcpy(filename,InFile[i]);
						printf("Working %d of %d '%s'\n",i+1,numfile,filename);
						fprintf(FpOut,"Working %d of %d '%s'\n",
							i+1,numfile,filename);
						strcpy(string,filename);
						string[5]='\0';
						if(split<=0)
							makeraw(filename,outfile,"at");
						else if(splitraw(filename,num)==-5)
							break;
					}
				}
			}
			printf("Total segments = %ld\n",Size);
			fprintf(FpOut,"Total segments = %ld\n",Size);
		}
		if(misses>0)
			exit(0);
		fprintf(FpOut,"\nTotal Attribute 1\n");
		for(i=0;i<1000;i++)
			if(TAtr1[i]>0)
				fprintf(FpOut,"%3d %6ld      ",i,TAtr1[i]);
		fprintf(FpOut,"\nTotal Attribute 2\n");
		for(i=0;i<1000;i++)
			if(TAtr2[i]>0)
				fprintf(FpOut,"%3d %6ld      ",i,TAtr2[i]);
		fprintf(FpOut,"\nFirst Attribute 1\n");
		for(i=0;i<1000;i++)
			if(Atr1[i]>0)
				fprintf(FpOut,"%3d %6ld      ",i,Atr1[i]);
		fprintf(FpOut,"\nFirst Attribute 2\n");
		for(i=0;i<1000;i++)
			if(Atr2[i]>0)
				fprintf(FpOut,"%3d %6ld      ",i,Atr2[i]);
		if(FpOut);
			fclose(FpOut);
		exit(0);
	}while(ans!='x');
}


/***********************************************************************
**
**
**
**
************************************************************************/

int splitraw(infile,num)

char *infile;
int num;

{
	int i,j,k,l;
	int n=0,m=0,val;
	FILE *fpin,*fpout;
	char string[100];
	double lat,lon,x,y,lat0,lon0,x0,y0;
	double err;
	int zone;
	long num_pts,h[8],atr[2],num_atr,a[2],p;
	long l_num=0;

	fpin=fopen(infile,"rt");
	if(!fpin)
	{
		printf("Could not open '%s'.\n\n",infile);
		fprintf(FpOut,"Could not open '%s'.\n\n",infile);
		return(0);
	}
	do
	{
		fscanf(fpin,"%s",string);
	}while(strcmpi(string,"NW")!=0);
	fscanf(fpin,"%lf%lf%lf%lf",&lat0,&lon0,&x0,&y0);
	printf("%s Corner:",string);
	fprintf(FpOut,"test values for '%s':\n",string);
	printf("  lat = %0.3lf  lon = %0.3lf",lat0,lon0);
	fprintf(FpOut,"lat/lon  = %10.3lf %11.3lf\n",lat0,lon0);
	fprintf(FpOut,"  x/y    = %10.3lf %11.3lf\n",x0,y0);
	zone=zone_number(lon0);
	printf("  zone = %d\n",zone);
	fprintf(FpOut,"zone = %d\n",zone);
	ull_xy_e(&x,&y,lat0,lon0,P);
	fprintf(FpOut,"test x/y = %10.3lf %11.3lf\n",x,y);
	err=sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
	fprintf(FpOut,"error = %6.2lf meters\n",err);
	if(err>10.0)
	{
		printf("error > 10.0 meters.  Do you wish to continue?  (y r n)\n\n");
fprintf(FpOut,"error > 10.0 meters.  Do you wish to continue?  (y r n)\n\n");
		if(getch()!='y')
			return(-1);
	}
	while(fscanf(fpin,"%s",string)>0)
	{
		if(kbhit()>0)
		{
			val=getch();
			if(val==27)
				return(-5);
		}
		if(string[0]=='L'&&check_char(string[1])!='L')
		{
			if(strcmpi(string,"L")==0)
				for(i=0;i<8;i++)
					fscanf(fpin,"%ld",h+i);
			else
			{
				sscanf(string+1,"%ld",h);
				for(i=1;i<8;i++)
					fscanf(fpin,"%ld",h+i);
			}
			if(h[0]%100==0)
				printf("%ld%c",h[0],Cr);
			l_num+=1;
			atr[0]=atr[1]=0;
			num_pts=h[5];
			num_atr=h[6];
			if(num_pts>MAX_PTS)
			{
				printf("Too many points in vector.\n\n");
				fprintf(FpOut,"Too many points in vector.\n\n");
				exit(0);
			}
			for(k=0;k<num_pts;k++)
				fscanf(fpin,"%lf%lf",X+k,Y+k);
			for(k=0;k<num_atr;k++)
			{
				fscanf(fpin,"%ld%ld",a,a+1);
				TAtr1[a[0]]+=1;
				TAtr2[a[1]]+=1;
				if(
					(atr[0]==0&&a[0]>0)||
					(atr[0]>Attrib1[num]&&a[0]==Attrib1[num])||
					(atr[0]==Attrib1[num]&&a[0]==Attrib1[num]&&a[1]>0&&a[1]<atr[1])
					)
				{
					atr[0]=a[0];
					atr[1]=a[1];
				}
			}
			if(atr[0]>Attrib1[num])
			{
				p=atr[0]%10;
				atr[1]=a[1]+p*1000;
			}
			Atr1[atr[0]]+=1;
			Atr2[atr[1]]+=1;
			l=0;
			if(atr[0]==Attrib1[num])
				l=Assn[atr[1]];

if(atr[1]>999)
{
	printf("l_num = %ld atr[0]=%4ld  atr[1]=%4ld  Attrib1[%d]=%4ld  l=%4d\n",
		l_num,atr[0],atr[1],num,Attrib1[num],l);
	fprintf(FpOut,
		"l_num = %ld atr[0]=%4ld  atr[1]=%4ld  Attrib1[%d]=%4ld  l=%4d\n",
		l_num,atr[0],atr[1],num,Attrib1[num],l);
}

			if(num_atr>0)		/* check for boundary */
			{
				fprintf(Fp[l],"%5ld",atr[1]);
				for(k=0;k<num_pts;k++)
				{
					if(k%3==0)
						fprintf(Fp[l],"\n");
					else
						fprintf(Fp[l],"  ");
					uxy_ll_e(zone,X[k],Y[k],&lat,&lon,P);
					fprintf(Fp[l],"%9.5lf %10.5lf",lat,lon);
				}
				fprintf(Fp[l],"//\n");
				n+=1;
				FSize[l]+=1;
				if(FSize[l]%9000==0)
				{
					if(Fp[l])
						fclose(Fp[l]);
					sprintf(string,"%s%s%02d.raw",StateId,FName[l],FNum[l]-1);
					printf("File '%s' is full.\n",string);
					sprintf(string,"%s%s%02d.raw",StateId,FName[l],FNum[l]);
printf("l=%d  num=%d  FName[l]='%s'  FNum[l]=%d\n",l,num,FName[l],FNum[l]);
					Fp[l]=fopen(string,"wt");
					if(!Fp[l])
					{
						printf("Could not open '%s' to write text.\n\n",string);
						exit(0);
					}
					FNum[l]+=1;
					printf("Opening file '%s' and continuing.\n",string);
					fprintf(FpOut,"Opening file '%s' and continuing.\n",string);
				}
			}
			else
				m+=1;
		}
	}
	if(fpin)
		fclose(fpin);
	printf("There are %d segments.\n",m+n);
	fprintf(FpOut,"There are %d segments.\n",m+n);
	printf("%d boundary and %d used.\n\n",m,n);
	fprintf(FpOut,"%d boundary and %d used.\n\n",m,n);
}




/***********************************************************************
**
**
**
**
************************************************************************/

int set_files(n)

int n;

{
	int i,j,k;
	FILE *fp;
	char string[100],str1[100],str2[100];
	int num,m;

	sprintf(string,"%s.ctl",Type[n].id);
	printf("Trying '%s'\n",string);
	fp=fopen(string,"rt");
	if(!fp)
	{
		printf("Could not find '%s'\n.",string);
		return(-1);
	}
	for(i=0;i<1000;i++)
		Assn[i]=0;
	fscanf(fp,"%s",string);
	if(strcmpi(string,Type[n].id)!=0)
	{
		printf("File starts with '%s' not '%s'\n",string,Type[n].id);
		return(-2);
	}
	fscanf(fp,"%s%d",string,&num);
	if(num<1||num>MAX_FILES)
	{
		printf("Invalid number of files.\n");
		return(-3);
	}
	printf("There are %d file types.\n",num);
/*
	printf("Do you wish to split files?  (y or n)\n\n");
	if(getch()!='y')
		return(-4);
*/
	for(i=0;i<num;i++)
		FNum[i]=1;
	for(i=0;i<num;i++)
	{
		fscanf(fp,"%s%s%d",str1,str2,&m);
		do
		{
			if(Fp[i])
				fclose(Fp[i]);
			sprintf(string,"%s%02d.bin",str1,FNum[i]);
			printf("Checking '%s' with %d entries.\n",string,m);
			Fp[i]=fopen(string,"rt");
			FNum[i]+=1;
		}while(Fp[i]);
		strcpy(FName[i],str1);
		sprintf(string,"%s%s%02d.raw",StateId,str1,FNum[i]-1);
		printf("Checking '%s' with %d entries.\n",string,m);
		Fp[i]=fopen(string,"wt");
		if(!Fp[i])
		{
			printf("Could not open '%s' to write text.\n\n",string);
			exit(0);
		}
		for(j=0;j<m;j++)
		{
			if(fscanf(fp,"%d",&k)!=1)
			{
				printf("Bad entry.\n\n");
				exit(0);
			}
			printf("%8d",k);
			Assn[k]=i;
		}
		if(m>0)
			printf("\n");
	}
	if(fp)
		fclose(fp);
	return(num);
}



/***********************************************************************
**
**
**
**
************************************************************************/

int makeraw(infile,outfile,mode)

char *infile,*outfile,*mode;

{
	int i,j,k;
	int n=0,m=0;
	FILE *fpin,*fpout;
	char string[100];
	double lat,lon,x,y,lat0,lon0,x0,y0;
	double err;
	int zone;
	long num_pts,h[8],atr[2],num_atr,a[2];

	fpin=fopen(infile,"rt");
	if(!fpin)
	{
		printf("Could not open '%s'.\n\n",infile);
		fprintf(FpOut,"Could not open '%s'.\n\n",infile);
		return(0);
	}
	fpout=fopen(outfile,mode);
	if(!fpout)
	{
		printf("Could not open '%s'.\n\n",outfile);
		fprintf(FpOut,"Could not open '%s'.\n\n",outfile);
		return(0);
	}
	do
	{
		fscanf(fpin,"%s",string);
	}while(strcmpi(string,"NW")!=0);
	fscanf(fpin,"%lf%lf%lf%lf",&lat0,&lon0,&x0,&y0);
	printf("%s Corner:",string);
	fprintf(FpOut,"test values for '%s':\n",string);
	printf("  lat = %0.3lf  lon = %0.3lf  ",lat0,lon0);
	fprintf(FpOut,"lat/lon  = %10.3lf %11.3lf\n",lat0,lon0);
	fprintf(FpOut,"  x/y    = %10.3lf %11.3lf\n",x0,y0);
	zone=zone_number(lon0);
	printf("zone = %d\n",zone);
	fprintf(FpOut,"zone = %d\n",zone);
	ull_xy_e(&x,&y,lat0,lon0,P);
	fprintf(FpOut,"test x/y = %10.3lf %11.3lf\n",x,y);
	err=sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
	fprintf(FpOut,"error = %6.2lf meters\n",err);
	if(err>10.0)
	{
		printf("error > 10.0 meters.  Do you wish to continue?  (y r n)\n\n");
fprintf(FpOut,"error > 10.0 meters.  Do you wish to continue?  (y r n)\n\n");
		if(getch()!='y')
			return(-1);
	}
	while(fscanf(fpin,"%s",string)>0)
	{
		if(string[0]=='L')
		{
			if(strcmpi(string,"L")==0)
				for(i=0;i<8;i++)
					fscanf(fpin,"%ld",h+i);
			else
			{
				sscanf(string+1,"%ld",h);
				for(i=1;i<8;i++)
					fscanf(fpin,"%ld",h+i);
			}
			if(h[0]%100==0)
				printf("%ld%c",h[0],Cr);
			num_pts=h[5];
			num_atr=h[6];
			if(num_pts>MAX_PTS)
			{
				printf("Too many points in vector.\n\n");
				fprintf(FpOut,"Too many points in vector.\n\n");
				exit(0);
			}
			for(k=0;k<num_pts;k++)
				fscanf(fpin,"%lf%lf",X+k,Y+k);
			for(k=0;k<num_atr;k++)
			{
				fscanf(fpin,"%ld%ld",a,a+1);
				TAtr1[a[0]]+=1;
				TAtr2[a[1]]+=1;
				if(k==0)
				{
					atr[0]=a[0];
					atr[1]=a[1];
					Atr1[a[0]]+=1;
					Atr2[a[1]]+=1;
				}
			}
			if(num_atr>0)		/* check for boundary */
			{
				fprintf(fpout,"%5ld",atr[1]);
				for(k=0;k<num_pts;k++)
				{
					if(k%3==0)
						fprintf(fpout,"\n");
					else
						fprintf(fpout,"  ");
					uxy_ll_e(zone,X[k],Y[k],&lat,&lon,P);
					fprintf(fpout,"%9.5lf %10.5lf",lat,lon);
				}
				fprintf(fpout,"//\n");
				n+=1;
				Size+=1;
				if(Size%9000==0)
				{
					if(fpout)
						fclose(fpout);
					printf("File '%s' is full.\n",outfile);
					fprintf(FpOut,"File '%s' is full.\n",outfile);
					outfile[5]+=1;
					printf("Opening file '%s' and continuing.\n",outfile);
					fprintf(FpOut,"Opening file '%s' and continuing.\n",outfile);
					fpout=fopen(outfile,"wt");
				}
			}
			else
				m+=1;
		}
	}
	if(fpin)
		fclose(fpin);
	if(fpout)
		fclose(fpout);
	printf("There are %d segments.\n",m+n);
	fprintf(FpOut,"There are %d segments.\n",m+n);
	printf("%d boundary and %d used.\n\n",m,n);
	fprintf(FpOut,"%d boundary and %d used.\n\n",m,n);
}


/***********************************************************************
**
**	returns:
**
**		l -- lower case letter
**		L -- upper case letter
**		n -- number
**		p -- punctuation
**		w -- white space
**		i -- illegal
**
************************************************************************/

char check_char(char c)

{
	if(c<0x9)
		return('i');
	if(c<0xe)
		return('w');
	if(c<0x1f)
		return('i');
	if(c==0x20)
		return('w');
	if(c<0x2f)
		return('p');
	if(c<0x3a)
		return('n');
	if(c<0x41)
		return('p');
	if(c<0x5b)
		return('L');
	if(c<0x61)
		return('p');
	if(c<0x7b)
		return('L');
	if(c<0x7e)
		return('p');
	else
		return('i');

}
                       