/**************************************************************************
 **
 ** Program:    vecta2b
 **
 ** Purpose:    To convert ASCII vector data to a binary format suitable
 **             for use with the USGS image viewing programs IMVIS and
 **             IMGVIEW.
 **
 ** Usage:      vecta2b infile outfile [/p] [/o]
 **
 **             infile = the input file name (complete file name)
 **            outfile = the output file name WITHOUT any extension.
 **                     The program uses this name to generate file
 **                     name 'outfile.bin', 'outfile.hdr', and 'outfile.atr'
 **                 /p = optional flag to write program information into
 **                      a file suitable for printing later.
 **                 /o = optional flag to reorder the data.
 **
 ****************************************************************************
 */
#include <stdio.h>
#include <string.h>

#define MAX_SEG 11000
#define SEGSIZE 65536

float Maxlat[MAX_SEG],Minlat[MAX_SEG],Maxlon[MAX_SEG],Minlon[MAX_SEG];
float Array[MAX_SEG];
long Offset[MAX_SEG];
int Num[MAX_SEG];

char FileIn[80],FileOdr[80],FileBin[80],FileHdr[80],FileAtr[80];
FILE *FpIn,*FpOdr,*FpBin,*FpHdr,*FpPrn,*FpAtr;

int Order[MAX_SEG];

char String[2][1000];
float Lat,Lon,oLat=0.0,oLon=0.0;
int NumSegs;
int Print=0,Ord=0;

void reorder();
long count_segs();
void file_names();
void sort2();

main(argc,argv)

int argc;
char *argv[];

{
	int i,j,k;
	char ans;

	for(i=1;i<argc;i++)
	{
		if(argv[i][0]=='/'&&argv[i][1]=='p')
		{
			Print=1;
			printf("PRINT == ON\n");
			FpPrn=fopen("vecta2b.prn","wt");
		}
		if(argv[i][0]=='/'&&argv[i][1]=='o')
		{
			printf("ORDER == ON\n");
			Ord=1;
		}
	}
	file_names(argc,argv);

	do
	{
		printf("\n\n");
		printf("   c -- count segments in file\n");
		printf("   R -- reorder file and make binary file without dupes\n");
		printf("   r -- reorder file and make binary file\n");
		printf("   p -- same as 'r' but not in order\n");
		printf("\n   x -- exit program\n");

		ans=getch();

		if(Print==1)
			fprintf(FpPrn,"option = %c\n",ans);

		if(ans=='r')
		{
			reorder(1);
			if(Ord==1)
				fclose(FpOdr);
			exit(0);
		}
		if(ans=='p')
		{
			reorder(2);
			if(Ord==1)
				fclose(FpOdr);
			exit(0);
		}
		if(ans=='R')
		{
			reorder(0);
			if(Ord==1)
				fclose(FpOdr);
			exit(0);
		}
		if(ans=='c')
		{
			printf("There are %ld segments in file.\n",count_segs());           
			if(Print==1)
				fprintf(FpPrn,"There are %ld segments in file.\n",count_segs());
		}
	}while(ans!='x'||argc>2);
	fclose(FpIn);
	if(Ord==1)
		fclose(FpOdr);
	fclose(FpBin);
	fclose(FpHdr);
	fclose(FpPrn);
	fclose(FpAtr);
}

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

void file_names(argc,argv)

int argc;
char *argv[];

{
	char string[100];
	char Drive[5];
	char Dir[256];
	char Fname[10];
	char Ext[5];

	if(argc<2)
	{
		printf("*************** VECTA2B ******************\n\n");
		printf("This program converts ASCII vector data to binary\n");
		printf("files suitable for use with USGS image viewing programs\n");
		printf("IMVIS and IMGVIEW.\n\n");
		printf("USAGE: vecta2b infile outfile [/p] [/o]\n\n");
		printf("    infile = the input file name (complete file name)\n");
		printf("   outfile = the output file name WITHOUT any extensions.\n");
		printf("             the output files will be named 'outfile.hdr'\n");
		printf("             and 'outfile.bin'\n");
		printf("        /p = optional flag to include the generation of a\n");
		printf("             printer file.\n");
		printf("        /o = optional flag to reorder the data.\n");
		exit(0);
	}
	else
	strcpy(FileIn,argv[1]);
	FpIn=fopen(FileIn,"rb");
	if(!FpIn)
	{
		printf("***** Could not open '%s'. *****\n\n",FileIn);
		if(Print==1)
			fprintf(FpPrn,"Could not open '%s'.\n\nHIT ANY KEY TO CONTINUE\n\n",
				FileIn);
		exit(0);
	}
	else if(Print==1)
		fprintf(FpPrn,"Working '%s'\n",FileIn);

	_splitpath(FileIn,Drive,Dir,Fname,Ext);
	strcpy(FileOdr,Fname);
	strcat(FileOdr,".odr");
	if(Ord==1)
		FpOdr=fopen(FileOdr,"wt");
	strcpy(FileBin,argv[2]);
	strcat(FileBin,".bin");
	FpBin=fopen(FileBin,"wb");
	strcpy(FileHdr,argv[2]);
	strcat(FileHdr,".hdr");
	FpHdr=fopen(FileHdr,"wb");
	strcpy(FileAtr,argv[2]);
	strcat(FileAtr,".atr");
	FpAtr=fopen(FileAtr,"wb");
}



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

long count_segs()

{
	int i,j1,j2,k,n=0;
	char filename[100];
	int state,val,secnum,num,numsec=0;
	long lval,hit,offset,numseg=0,maxseg=MAX_SEG;
	FILE *fpin,*fpout,*fpout2;
	float fval,lat,lon;

	if(FpIn)
	{
		rewind(FpIn);
		offset=ftell(FpIn);
		while(fscanf(FpIn,"%d",&secnum)>0)
		{
			numseg+=1;
			fscanf(FpIn,"%s%s",String[0],String[1]);
			if(String[1][strlen(String[1])-1]!='/')
			{
				do
				{
					fscanf(FpIn,"%s%s",String[0],String[1]);
				}while(String[1][strlen(String[1])-1]!='/');                
			}
		}
	}
	NumSegs=numseg;
	if(numseg>maxseg)
	{
		printf("\n\nWARNING TOO MANY SEGMENTS TO PROCESS!!!!!\n\n");
		printf("There are %ld segments and only %d are allowed.\n\n",
			numseg,MAX_SEG);
		printf("HIT ANY KEY TO CONTINUE.\n\n");
		if(Print==1)
		{
			fprintf(FpPrn,"\n\nWARNING TOO MANY SEGMENTS TO PROCESS!!!!!\n\n");
			fprintf(FpPrn,"There are %ld segments and only %d are allowed.\n\n",
				numseg,MAX_SEG);
		}
	}
	return(numseg);
}


/********************************************************************
**
**  iop == 2 --> do not put in order
**
********************************************************************* */

void reorder(iop)

int iop;

{
	int i,j1,j2,k,n=0,m=0,nptr;
	char filename[100];
	int state,val,secnum,num,numsec=0,off=0,fst;
	long lval,hit,offset,lsecnum,offset6,attrib,SegPointer=SEGSIZE,mptr;
	float fval,lat,lon,mll[4],dist,lato,lono;
	int base=2,nseg,eof=0,numread;
	char cval,retn=13;
	FILE *fptemp;

	fptemp=fopen("reorder.tmp","w+b");

	printf("iop = %d\n",iop);

	m=0;
	offset=0;
	Offset[m]=offset;
	printf("Setting offsets:\n");
	while((cval=fgetc(FpIn))!=EOF)
	{
		if(cval=='/')
		{
			offset+=1;
			m+=1;
			while((cval=fgetc(FpIn))!=20&&cval!='-'&&
				(cval<'0'||cval>'9')&&cval!=EOF)
				offset+=1;
			if(m>=MAX_SEG)
			{
				printf("Exiting program -- Too many segments:  number now = %d\n",
					m);
				exit(0);
			}
			printf("%c%5d",retn,m);
			Offset[m]=offset-1;
			offset+=1;
		}
		else
			offset+=1;
	}
	printf("\n");
	nseg=m;
	m=0;
	if(FpIn)
	{
		rewind(FpIn);
		printf("Scanning segments and setting lat/lon limits\n");
		printf("              of %d",nseg);
		while((numread=fscanf(FpIn,"%ld",&lsecnum))>0)
		{
			fwrite((char *)&lsecnum,sizeof(long),1,fptemp);
			if(numread==0)
				eof=1;
			if(lsecnum>32768)
				secnum=lsecnum%100000;
			else
				secnum=lsecnum;
			Maxlat[m]=-360.0;
			Maxlon[m]=-360.0;
			Minlat[m]= 360.0;
			Minlon[m]= 360.0;
			printf("%c%5d%8d",retn,m+1,secnum);
			numread=fscanf(FpIn,"%s%s",String[0],String[1]);
			if(numread==0)
				eof=1;
			sscanf(String[0],"%f",&Lat);
			sscanf(String[1],"%f",&Lon);
			if(Lat>Maxlat[m])Maxlat[m]=Lat;
			if(Lat<Minlat[m])Minlat[m]=Lat;
			if(Lon>Maxlon[m])Maxlon[m]=Lon;
			if(Lon<Minlon[m])Minlon[m]=Lon;
			numsec+=1;
			num=1;
			if(String[1][strlen(String[1])-1]!='/')
			{
				do
				{
					numread=fscanf(FpIn,"%s%s",String[0],String[1]);
					if(numread==0)
					{
						eof=1;
						break;
					}
					sscanf(String[0],"%f",&Lat);
					sscanf(String[1],"%f",&Lon);
					if(Lat>Maxlat[m])Maxlat[m]=Lat;
					if(Lat<Minlat[m])Minlat[m]=Lat;
					if(Lon>Maxlon[m])Maxlon[m]=Lon;
					if(Lon<Minlon[m])Minlon[m]=Lon;
					num+=1;
				}while(String[1][strlen(String[1])-1]!='/'&&eof==0);                
			}
			Num[m]=num;
			m+=1;
		}
	}
	NumSegs=m;
	rewind(FpIn);
	printf("\n");
	fwrite((char *)&NumSegs,sizeof(int),1,FpBin);
	fwrite((char *)&NumSegs,sizeof(int),1,FpHdr);
	
	for(i=0;i<NumSegs;i++)
	{
		Order[i]=i;
		Array[i]=Minlon[i];
	}
	k=0;
	if(iop!=2&&NumSegs>2)
	{
		printf("Sorting segments by minimum longitude.\n");
		sort2(NumSegs,Array,Order);
	}
	num=0;
	printf("Loading '.hdr','.bin' and '.atr' files\n");
	printf("      of %d",nseg);
	for(i=0;i<NumSegs;i++)
	{
		printf("%c%5d",retn,i+1);
		j1=Order[i];
		if(i>0)
			j2=Order[i-1];
		if(i==0||iop==1||iop==2||
			Num[j1]!=Num[j2]||
			Maxlon[j1]!=Maxlon[j2]||
			Minlon[j1]!=Minlon[j2]||
			Maxlat[j1]!=Maxlat[j2]||
			Minlat[j1]!=Minlat[j2])
		{
			offset=ftell(FpBin);
			mptr = sizeof(long)+(Num[j1]*2+4)*sizeof(float);
			mptr += offset;
			if( mptr >= SegPointer )     /* Will we cross a segment boundary? */
			{
				mptr = 1 + (SegPointer - offset)/sizeof(int);
				nptr = (int) mptr;
				for(k=0;k<nptr;k++)
					fwrite((char *)&nptr,sizeof(int),1,FpBin);
				SegPointer += SEGSIZE;
				offset = ftell(FpBin);
			}
			fseek(FpIn,Offset[j1],SEEK_SET);
			fscanf(FpIn,"%ld",&lval);
			attrib=lval;
			if(Ord==1)
				fprintf(FpOdr,"%4d",i);
			val=Num[j1];
			if(val>0)
				fwrite((char *)&val,sizeof(int),1,FpBin);
			fwrite((char *)&offset,sizeof(long),1,FpHdr);
			mll[0]=Minlon[j1];
			mll[1]=Maxlon[j1];
			mll[2]=Minlat[j1];
			mll[3]=Maxlat[j1];
			fwrite((char *)mll,sizeof(float),4,FpHdr);
			fwrite((char *)mll,sizeof(float),4,FpBin);
			fwrite((char *)&attrib,sizeof(long),1,FpAtr);
			for(k=0;k<Num[j1];k++)
			{
				fscanf(FpIn,"%f%f",&lat,&lon);
				if(k%4!=0)
				{
					if(Ord==1)
						fprintf(FpOdr," %6.3f %8.3f",lat,lon);
				}
				else
				{
					if(Ord==1)
						fprintf(FpOdr,"\n%6.3f %8.3f",lat,lon);
				}
				fwrite((char *)&lat,sizeof(float),1,FpBin);
				fwrite((char *)&lon,sizeof(float),1,FpBin);
			}
			if(Ord==1)
				fprintf(FpOdr,"//\n");
		}
		else if(iop==0)
			num+=1;
	}
	printf("\n");
	if(iop==0)
	{
		NumSegs-=num;
		rewind(FpBin);
		rewind(FpHdr);
		fwrite((char *)&NumSegs,sizeof(int),1,FpBin);
		fwrite((char *)&NumSegs,sizeof(int),1,FpHdr);
		printf("deleted %d segments\n",num);
		if(Print==1)
			fprintf(FpPrn,"deleted %d segments\n",num);
	}
	fclose(fptemp);
	unlink("reorder.tmp");
}


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

void sort2(n,ra,ib)

int n,ib[];
float ra[];

{
	int l,j,ir,i;
	float rra;
	int iib;

	l=(n>>1)+1;
	ir=n-1;
	for(;;)
	{
		if(l>1)
		{
			rra=ra[--l];
			iib=ib[l];
		}
		else
		{
			rra=ra[ir];
			iib=ib[ir];
			ra[ir]=ra[1];
			ib[ir]=ib[1];
			if(--ir==1)
			{
				ra[1]=rra;
				ib[1]=iib;
				return;
			}
		}
		i=l;
		j=l<<1;
		while(j<=ir)
		{
			if(j<ir&&ra[j]<ra[j+1])++j;
			if(rra<ra[j])
			{
				ra[i]=ra[j];
				ib[i]=ib[j];
				j+=(i=j);
			}
			else
				j=ir+1;
		}
		ra[i]=rra;
		ib[i]=iib;
	}
}


