/**********************************************************************
 
	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 <string.h>
#include <ctype.h>

#include "kiban2svg.h"
#include "stdio.h"
#include "arc_data.h"
#include "poly_data.h"
#include "attr_data.h"
#include "pnt_data.h"
#include "zuyou_data.h"
#include "map_matrix.h"

#ifndef MAX
#define	MAX( x, y )	( x > y ? x : y )
#define	MIN( x, y )	( x < y ? x : y )
#endif

#ifndef _WIN32
#define stricmp strcasecmp
#else
#include <direct.h>
#endif

static char *LineColorTable[] = {
	"none",
	"none",
	CL_SI_TYO_LINE,
	CL_TYOME_LINE,
	CL_GAIKU_LINE,
	CL_ROAD_LINE,
	CL_KOKUDOU_LINE,
	CL_KASEN_LINE,
	CL_KASEN2_LINE,
	CL_OTHERS_LINE,
	CL_TETUDOU_LINE,
	CL_ZYOUTI_LINE,
	CL_EKI_LINE,
	CL_MIZU_LINE,
	CL_TATEMONO_LINE,
	CL_KIJUNTEN_LINE
};

static char *FillColorTable[] = {
	"none",
	"none",
	CL_SI_TYO_FILL,
	CL_TYOME_FILL,
	CL_GAIKU_FILL,
	CL_ROAD_FILL,
	CL_KOKUDOU_FILL,
	CL_KASEN_FILL,
	CL_KASEN2_FILL,
	CL_OTHERS_FILL,
	CL_TETUDOU_FILL,
	CL_ZYOUTI_FILL,
	CL_EKI_FILL,
	CL_MIZU_FILL,
	CL_TATEMONO_FILL,
	CL_KIJUNTEN_FILL
};

static void ToFullPath(char *dest_path, const char *src_path)
{
	int add_cwd_flag;
	char app_dir[MAX_PATH+1];
#ifdef _WIN32
	if(strlen(src_path)<=1)
		add_cwd_flag = 1;
	if(src_path[1] == ':')
		add_cwd_flag = 0;
	else if( (src_path[0]=='\\') && (src_path[1]=='\\') )
		add_cwd_flag = 0;
	else
		add_cwd_flag = 1;
#else
	add_cwd_flag = (src_path[0] == '/') ? 0:1;
#endif
	
	if(add_cwd_flag){
		getcwd(app_dir, MAX_PATH);
		sprintf(dest_path, "%s%c%s", app_dir, PATH_DEVIDER, src_path);
	}
	else{
		strcpy(dest_path, src_path);
	}
}

void LoadConfigure(FILE *fp){
	char buff[4096];
	char *p,*p2;
	char name[64];
	char value[64];
	
	while(fgets(buff, 4096, fp)){
		chop(buff);
		if(buff[0]=='#')
			continue;
		memset(name, 0, sizeof(name));
		memset(value, 0, sizeof(value));
		p = buff;
		while(isspace(*p)){
			++p;
		}
		if(!*p)
			continue;
		p2 = p+strcspn(p, " =\t\r\n");
		strncpy(name, p, p2-p);
		if(!*p2)
			continue;
		p = p2+strspn(p2, " \r\n\t=");
		if(!*p)
			continue;
		p2 = p+strcspn(p, " \r\n\t");
		strncpy(value, p, p2-p);
		
		if(stricmp(name, "line_si_tyo")==0){
			LineColorTable[ID_SI_TYO] = strdup(value);
		}
		else if(stricmp(name, "line_tyome")==0){
			LineColorTable[ID_TYOME] = strdup(value);
		}
		else if(stricmp(name, "line_gaiku")==0){
			LineColorTable[ID_GAIKU] = strdup(value);
		}
		else if(stricmp(name, "line_road")==0){
			LineColorTable[ID_ROAD] = strdup(value);
		}
		else if(stricmp(name, "line_kokudou")==0){
			LineColorTable[ID_KOKUDOU] = strdup(value);
		}
		else if(stricmp(name, "line_kasen")==0){
			LineColorTable[ID_KASEN] = strdup(value);
		}
		else if(stricmp(name, "line_kasen2")==0){
			LineColorTable[ID_KASEN2] = strdup(value);
		}
		else if(stricmp(name, "line_others")==0){
			LineColorTable[ID_OTHERS] = strdup(value);
		}
		else if(stricmp(name, "line_tetudou")==0){
			LineColorTable[ID_TETUDOU] = strdup(value);
		}
		else if(stricmp(name, "line_zyouti")==0){
			LineColorTable[ID_ZYOUTI] = strdup(value);
		}
		else if(stricmp(name, "line_eki")==0){
			LineColorTable[ID_EKI] = strdup(value);
		}
		else if(stricmp(name, "line_mizu")==0){
			LineColorTable[ID_MIZU] = strdup(value);
		}
		else if(stricmp(name, "line_tatemono")==0){
			LineColorTable[ID_TATEMONO] = strdup(value);
		}
		else if(stricmp(name, "line_kijunten")==0){
			LineColorTable[ID_KIJUNTEN] = strdup(value);
		}
		/* fill */
		else if(stricmp(name, "fill_si_tyo")==0){
			FillColorTable[ID_SI_TYO] = strdup(value);
		}
		else if(stricmp(name, "fill_tyome")==0){
			FillColorTable[ID_TYOME] = strdup(value);
		}
		else if(stricmp(name, "fill_gaiku")==0){
			FillColorTable[ID_GAIKU] = strdup(value);
		}
		else if(stricmp(name, "fill_road")==0){
			FillColorTable[ID_ROAD] = strdup(value);
		}
		else if(stricmp(name, "fill_kokudou")==0){
			FillColorTable[ID_KOKUDOU] = strdup(value);
		}
		else if(stricmp(name, "fill_kasen")==0){
			FillColorTable[ID_KASEN] = strdup(value);
		}
		else if(stricmp(name, "fill_kasen2")==0){
			FillColorTable[ID_KASEN2] = strdup(value);
		}
		else if(stricmp(name, "fill_others")==0){
			FillColorTable[ID_OTHERS] = strdup(value);
		}
		else if(stricmp(name, "fill_tetudou")==0){
			FillColorTable[ID_TETUDOU] = strdup(value);
		}
		else if(stricmp(name, "fill_zyouti")==0){
			FillColorTable[ID_ZYOUTI] = strdup(value);
		}
		else if(stricmp(name, "fill_eki")==0){
			FillColorTable[ID_EKI] = strdup(value);
		}
		else if(stricmp(name, "fill_mizu")==0){
			FillColorTable[ID_MIZU] = strdup(value);
		}
		else if(stricmp(name, "fill_tatemono")==0){
			FillColorTable[ID_TATEMONO] = strdup(value);
		}
		else if(stricmp(name, "fill_kijunten")==0){
			FillColorTable[ID_KIJUNTEN] = strdup(value);
		}
	}
}

void MaximizeMapRect(MAP_RECT *pDestRect, MAP_RECT *pSrcRect)
{
	pDestRect->left = MIN(pDestRect->left, pSrcRect->left);
	pDestRect->right = MAX(pDestRect->right, pSrcRect->right);
	pDestRect->top = MIN(pDestRect->top, pSrcRect->top);
	pDestRect->bottom = MAX(pDestRect->bottom, pSrcRect->bottom);
}

void MaximizeRect(GB_RECT *pDestRect, GB_RECT *pSrcRect)
{
	pDestRect->left = MIN(pDestRect->left, pSrcRect->left);
	pDestRect->right = MAX(pDestRect->right, pSrcRect->right);
	pDestRect->top = MIN(pDestRect->top, pSrcRect->top);
	pDestRect->bottom = MAX(pDestRect->bottom, pSrcRect->bottom);
}

void GetMaxRectFromPoints(GB_RECT *pRect, const GB_POINT *pt, unsigned int nPoints)
{
	unsigned int i;
	for(i=0;i<nPoints;++i){
		pRect->left = MIN(pRect->left, pt->x);
		pRect->right = MAX(pRect->right, pt->x);
		pRect->top = MIN(pRect->top, pt->y);
		pRect->bottom = MAX(pRect->bottom, pt->y);
		++pt;
	}
}

int ReadKibanFileHeader(FILE *fp, KIBAN_FILE_HEADER *pHeader)
{
	char szBuff[512];
	char seps[]  = " ,\t\n";
	char *token;
	char *temp[5];
	if(!fgets(szBuff,sizeof(szBuff),fp)){
		return ID_ERR_FILE_FORMAT;
	}
	chop(szBuff);
	
	/* FH　　：FH */
	token = strtok( szBuff, seps );
	if(token==NULL || strcmp(token, "FH"))
		return ID_ERR_FILE_FORMAT;

	/* mapname：06nc183 */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	strcpy(pHeader->name,token);

	/* filename：06nc183\road\roadntwk.arc */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	strcpy(pHeader->file_name,token);
	
	/* total line count : 30 */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	
	/* IDRecord count ：2 */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	pHeader->record_count = atoi(token);
	
	/* 座標系フラグ：1 */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	
	/* 座標系番号：06 */
	token = strtok( NULL, seps );
	if(token==NULL)
		return ID_ERR_FILE_FORMAT;
	
	temp[0] = strtok( NULL, seps );
	temp[1] = strtok( NULL, seps);
	temp[2] = strtok( NULL, seps);
	temp[3] = strtok( NULL, seps);
	temp[4] = strtok( NULL, seps);
	
	if(temp[4]){
		pHeader->r.left = atof(temp[1]);
		pHeader->r.top = atof(temp[2]);
		pHeader->r.right = atof(temp[3]);
		pHeader->r.bottom = atof(temp[4]);
	}
	else{
		pHeader->r.left = atof(temp[0]);
		pHeader->r.top = atof(temp[1]);
		pHeader->r.right = atof(temp[2]);
		pHeader->r.bottom = atof(temp[3]);
	}
	
	return ID_ERR_NOERROR;
}

int FileNameToID(const char *szFileName ){
	char *szExt = strrchr(szFileName,'.');
	if(szExt == NULL){
		return ID_ERROR_EXT;
	}
	if(strcmp(szExt,".arc") == 0){
		return ID_ARC;
	}
	if(strcmp(szExt,".pgn") == 0){
		return ID_POLYGON;
	}
	if(strcmp(szExt,".pnt") == 0){
		return ID_POINT;
	}
	if(strcmp(szExt,".nod") == 0){
		return ID_NODE;
	}
	if(strcmp(szExt,".tie") == 0){
		return ID_TIE;
	}
	if(strcmp(szExt,".atr") == 0){
		return ID_ATTER;
	}
	if(strcmp(szExt,".txt") == 0){
		return ID_TEXT;
	}
	if(strcmp(szExt,".img") == 0){
		return ID_IMAGE;
	}
	return ID_ERROR_EXT;
}

int ReadKibanFile(char *szFileName, int nFileType, void **pData, int Flags){
	FILE *fp;
	char *p,*p2;
	void *pReturn;
	int code;
	pReturn=NULL;
	*pData=NULL;
	if(!*szFileName){
		return ID_ERR_FILE_OPEN;
	}
	fp = fopen(szFileName,"r");
	if(!fp){
		p = strrchr(szFileName, PATH_DEVIDER);
		if(*p){
			*p = '\0';
			p2 = strrchr(szFileName, PATH_DEVIDER);
			*p = PATH_DEVIDER;
			if(*p2)
				strtoupper(p2);
			else
				strtoupper(p);
		}
		fp = fopen(szFileName, "r");
	}

	if(!fp){
		return ID_ERR_FILE_OPEN;
	}
	switch(nFileType){
		case ID_ARC:
			{
				ARC_DATA *arc = malloc_arc_data();
				code = ReadArc(szFileName, fp, arc, Flags);
				if(code == ID_ERR_NOERROR)
					pReturn = arc;
				else
					free_arc_data(arc);
			}
			break;
		case ID_POLYGON:
			{
				POLY_DATA *poly = malloc_poly_data();
				code = ReadPoly(szFileName, fp, poly, Flags);
				if(code == ID_ERR_NOERROR)
					pReturn = poly;
				else
					free_poly_data(poly);
			}
			break;
		case ID_ATTER:
			{
				ATTR_DATA *attr = malloc_attr_data();
				code = ReadAttr(szFileName, fp, attr);
				if(code == ID_ERR_NOERROR)
					pReturn = attr;
				else
					free_attr_data(attr);
			}
			break;
		case ID_POINT:
			{
				PNT_DATA *pnt = malloc_pnt_data();
				code = ReadPnt(szFileName, fp, pnt, Flags);
				if(code == ID_ERR_NOERROR)
					pReturn = pnt;
				else
					free_pnt_data(pnt);
			}
			break;
		default:
			er_panic("unexpected fileid");
	}
	fclose(fp);
	*pData = pReturn;

	if(code != ID_ERR_NOERROR){
		fprintf(stderr, "::file loading error at %s. error-code:%d\n", szFileName, code);
		return code;
	}
	else{
		return ID_ERR_NOERROR;
	}
}

void PrintXMLHeader(FILE *fp, char *szEncode){
	fprintf(fp, "<?xml version=\"1.0\" encoding=\"%s\"?>\n",szEncode);
}

void PrintSVGHeader(FILE *fp, int nWidth, int nHeight, MAP_RECT *prViewBox){
	fprintf(fp,"<svg width=\"%d\" height=\"%d\" viewBox=\"%d %d %d %d\">\n",
		nWidth, nHeight, prViewBox->left, prViewBox->top,
		prViewBox->right-prViewBox->left, prViewBox->bottom-prViewBox->top);
}

void PrintSVGFooter(FILE *fp){
	fprintf(fp,"</svg>");
}

//
int BunruiNameToID(const char *szBunrui ){
	if(strcmp(szBunrui,"gyousei") == 0){
		return ID_GYOUSEI;
	}
	if(strcmp(szBunrui,"gaiku") == 0){
		return ID_GAIKU;
	}
	if(strcmp(szBunrui,"road") == 0){
		return ID_ROAD;
	}
	if(strcmp(szBunrui,"kokudou") == 0){
		return ID_KOKUDOU;
	}
	if(strcmp(szBunrui,"kasen") == 0){
		return ID_KASEN;
	}
	if(strcmp(szBunrui,"others") == 0){
		return ID_OTHERS;
	}
	if(strcmp(szBunrui,"mizu") == 0){
		return ID_MIZU;
	}
	if(strcmp(szBunrui,"tatemono") == 0){
		return ID_TATEMONO;
	}
	if(strcmp(szBunrui,"kijunten") == 0){
		return ID_KIJUNTEN;
	}
	return ID_ERROR_BUNRUI;
}

int Bunrui2SVG(FILE *fpSVG, FILE *fpInfo, const char *szMapRootPath, const char *szBunruiName){
	char szBunruiPath[MAX_PATH];
	char szFileName[MAX_PATH];
	ARC_DATA *pArcData=NULL;
	POLY_DATA *pPolyData1=NULL;	
	POLY_DATA *pPolyData2=NULL;
	ATTR_DATA *pAttrData1=NULL;
	ATTR_DATA *pAttrData2=NULL;
	ATTR_DATA *pAttrData3=NULL;
	PNT_DATA *pPntData=NULL;

	sprintf(szBunruiPath, "%s%s", szMapRootPath, szBunruiName);
	
	/* 行政の出力 */
	switch(BunruiNameToID(szBunruiName)){
		case ID_GYOUSEI:
			{
				/* 行政のアーク */
				sprintf(szFileName, "%s%cgyousei.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;

				/* 市町村のポリゴン */
				sprintf(szFileName, "%s%csi_tyo.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_SI_TYO_FILL, CL_SI_TYO_LINE);
				
				/* 市町村の属性 */
				sprintf(szFileName, "%s%csi_tyo.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
				
				/* 丁目のポリゴン */
				sprintf(szFileName, "%s%ctyome.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData2, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData2, CL_TYOME_FILL, CL_TYOME_LINE);

				/* 丁目の属性 */
				sprintf(szFileName, "%s%ctyome.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData2, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData2);
			}
			break;
		case ID_GAIKU:
			{
				/* 街区のアーク */
				sprintf(szFileName, "%s%cgaiku.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				
				/* 街区のポリゴン */
				sprintf(szFileName, "%s%cgaiku.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_GAIKU_FILL, CL_GAIKU_LINE);

				/* 街区の属性 */
				sprintf(szFileName, "%s%cgaiku.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_ROAD:
			{
				/* 道路のアーク */
				sprintf(szFileName, "%s%croadntwk.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				ArcData2SVG(fpSVG, pArcData, CL_ROAD_LINE);

				/* 道路の属性 */
				sprintf(szFileName, "%s%croad.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_KOKUDOU:
			{
				/* 国道のアーク */
				sprintf(szFileName, "%s%ckokudou.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				ArcData2SVG(fpSVG, pArcData, CL_KOKUDOU_LINE);

				/* 国道の属性 */
				sprintf(szFileName, "%s%ckokudou.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_KASEN:
			{
				/* 河川区域と中心線のアーク */
				sprintf(szFileName, "%s%ckasen.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				
				/* 河川区域のポリゴン */
				sprintf(szFileName, "%s%ckasen.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_KASEN_FILL, CL_KASEN_LINE);
				
				/* 河川の属性 */
				sprintf(szFileName, "%s%ckasen.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_OTHERS:
			{
				ARC_DATA arcTetudou;
				int nTetudouCount=0;
				int i=0,j=0;
				
				/* その他（鉄道と公園など場地）のアーク */
				sprintf(szFileName, "%s%cothers.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				
				/* 鉄道のアークのみ抽出して、SVG出力 */
				memcpy(&(arcTetudou.header.r), &(pArcData->header.r), sizeof(GB_RECT));
				
				/* 鉄道アークの数を取得 */
				for(i=0;i<pArcData->header.record_count;++i){
					if(strncmp(pArcData->record[i].code,"L23", 3) == 0){
						++nTetudouCount;
					}
				}

				/* 鉄道アークが見つかった場合 */
				if(nTetudouCount>0){
					arcTetudou.header.record_count = nTetudouCount;
					arcTetudou.record = (ARC_ID_RECORD*)malloc(sizeof(ARC_ID_RECORD) * nTetudouCount);
					/* 鉄道アークを抽出して格納 */
					j=0;
					for(i=0;i<pArcData->header.record_count;++i){
						if(strncmp(pArcData->record[i].code,"L23", 3) == 0){
							memcpy(&(arcTetudou.record[j]), &(pArcData->record[i]), sizeof(ARC_ID_RECORD));
							++j;
						}
					}
					/* 鉄道アークを出力 */
					ArcData2SVG(fpSVG, &arcTetudou, CL_TETUDOU_LINE);
					free(arcTetudou.record);
				}
				
				/* 鉄道の属性 */
				sprintf(szFileName, "%s%ctetudou.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
				
				/* 場地のポリゴン */
				sprintf(szFileName, "%s%czyouti.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_ZYOUTI_FILL, CL_ZYOUTI_LINE);
				
				/* 場地の属性 */
				sprintf(szFileName, "%s%czyouti.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData2, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData2);
				
				/* 駅の点 */
				sprintf(szFileName, "%s%ceki.pnt", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POINT, (void**)&pPntData, 0) == ID_ERR_NOERROR)
					Pnt2SVG(fpSVG, pPntData, PNT_TYPE_EKI, CL_EKI_FILL, CL_EKI_LINE);
				
				/* 駅の属性 */
				sprintf(szFileName, "%s%czyouti.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData3, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData3);
				
			}
			break;
		case ID_MIZU:
			{
				/* 内水面のアーク */
				sprintf(szFileName, "%s%cmizu.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				
				/* 内水面のポリゴン */
				sprintf(szFileName, "%s%cmizu.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_MIZU_FILL, CL_MIZU_LINE);

				/* 内水面の属性 */
				sprintf(szFileName, "%s%cmizu.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_TATEMONO:
			{
				/* 建物のアーク */
				sprintf(szFileName, "%s%ctatemono.arc", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ARC, (void**)&pArcData, 0) != ID_ERR_NOERROR)
					break;
				
				/* 建物のポリゴン */
				sprintf(szFileName, "%s%ctatemono.pgn", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POLYGON, (void**)&pPolyData1, 0) == ID_ERR_NOERROR)
					Poly2SVG(fpSVG, pArcData, pPolyData1, CL_TATEMONO_FILL, CL_TATEMONO_LINE);

				/* 建物の属性 */
				sprintf(szFileName, "%s%ctatemono.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
		case ID_KIJUNTEN:
			{
				/* 基準点 */
				sprintf(szFileName, "%s%csankaku.pnt", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_POINT, (void**)&pPntData, 0) != ID_ERR_NOERROR)
					break;
				Pnt2SVG(fpSVG, pPntData, PNT_TYPE_KIJUNTEN, CL_KIJUNTEN_FILL, CL_KIJUNTEN_LINE);
				
				/* 基準点の属性 */
				sprintf(szFileName, "%s%csankaku.atr", szBunruiPath, PATH_DEVIDER);
				if(ReadKibanFile(szFileName, ID_ATTER, (void**)&pAttrData1, 0) == ID_ERR_NOERROR)
					Attr2XML(fpInfo, pAttrData1);
			}
			break;
	}
	free_arc_data(pArcData);
	free_attr_data(pAttrData1);
	free_attr_data(pAttrData2);
	free_attr_data(pAttrData3);
	free_poly_data(pPolyData1);
	free_poly_data(pPolyData2);
	free_pnt_data(pPntData);
	return ID_ERR_NOERROR;
}

/* make a svgfile and infofile from MapRootDirectory */
int MapRoot2SVGFile(const char *szMapRootPath, const char *szSVGFile, const char *szInfoFile)
{
	FILE *fpSVG,*fpInfo;
	char sz[32];
	char *p;

	fpSVG = fopen(szSVGFile,"w");
	if(!fpSVG)
		return ID_ERR_FILE_OPEN;

	fpInfo = fopen(szInfoFile,"w");
	if(!fpInfo){
		fclose(fpSVG);
		return ID_ERR_FILE_OPEN;
	}
	
	PrintXMLHeader(fpSVG,"UTF-8");
	PrintXMLHeader(fpInfo,"Shift_JIS");
	
	fprintf(fpSVG, "<svg width=\"150\" height=\"200\" viewBox=\"0 0 1500 2000\">\n");

	ExtractFileName(szSVGFile,sz);
	p = &(sz[strlen(sz)-3]);
	strncpy(p,"html\0",5);
	fprintf(fpSVG, "<a xlink:href=\"%s\">\n", sz);
	
	fprintf(fpInfo, "<gbs>\n");
	
	{
		char szTemp[MAX_PATH];
		char szName[64];
		ExtractFileName(szMapRootPath, szName);
		sprintf(szTemp, "%s%s.txt", szMapRootPath, szName);
		ZuyouFile2XML(fpInfo, szTemp);
		
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "gyousei");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "gaiku");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "road");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "kokudou");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "kasen");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "others");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "mizu");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "tatemono");
		Bunrui2SVG(fpSVG, fpInfo, szMapRootPath, "kijunten");
	}
	
	fprintf(fpSVG, "</a>");
	fprintf(fpSVG, "</svg>");
	fprintf(fpInfo, "</gbs>");
	fclose(fpSVG);
	fclose(fpInfo);
	return ID_ERR_NOERROR;
}



int GetMaxMapRectProc(char *szFileName, long lParam){
	KIBAN2SVG_PROCESSING_INFO_DATA *pInfo; 
	char szFile[MAX_PATH];
	ZUYOU_DATA *pZuyou;
	int error;
	
	pInfo= (KIBAN2SVG_PROCESSING_INFO_DATA*)lParam;
	sprintf(szFile, "%s%s%c%s.txt", 
		pInfo->szKibanPath, szFileName, PATH_DEVIDER, szFileName);
	error = ReadZuyouDataFile(szFile, &pZuyou);
	if(error==ID_ERR_NOERROR){
		if(pInfo->rAllMap.left == pInfo->rAllMap.right)
			memcpy(&(pInfo->rAllMap),&(pZuyou->rMap), sizeof(pZuyou->rMap));
		else
			MaximizeMapRect(&(pInfo->rAllMap), &(pZuyou->rMap));
		free_zuyou_data(pZuyou);
	}
	else{
		printf("::reading zuyoufile error : %s error_code:%d\n", szFile, error);
	}
	return 0;
}

int CreateInfoFileProc(char *szFileName, long lParam){
	KIBAN2SVG_PROCESSING_INFO_DATA *pInfo; 
	char szFile[MAX_PATH];
	ZUYOU_DATA *pZuyou;
	int nColPos,nRowPos;
	int i;
	pZuyou = NULL;
	pInfo = (KIBAN2SVG_PROCESSING_INFO_DATA*)lParam;
	
	strcat(pInfo->szMapNames, szFileName);
	/* memcpy(&(pInfo->szMapNames[pInfo->nMapNameLength]), szFileName, strlen(szFileName)); */
	strcat(pInfo->szMapNames,",");
	pInfo->nMapNameCount++;
	pInfo->nMapNameLength = strlen(pInfo->szMapNames);
		
	sprintf(szFile, "%s%s%c%s.txt", 
		pInfo->szKibanPath, szFileName, PATH_DEVIDER, szFileName);
	if(ReadZuyouDataFile(szFile, &pZuyou)==ID_ERR_NOERROR){
		if(pInfo->nOneMapHeight == 0){
			pInfo->nOneMapHeight = pZuyou->rMap.bottom - pZuyou->rMap.top;
			pInfo->nOneMapWidth = pZuyou->rMap.right - pZuyou->rMap.left;
		}
		
		nColPos = (int)((pZuyou->rMap.left-pInfo->rAllMap.left)/pInfo->nOneMapWidth);
		nRowPos = (int)((pZuyou->rMap.top-pInfo->rAllMap.top)/pInfo->nOneMapHeight);
		
		pInfo->Cols[pInfo->nMapNameCount-1] = nColPos;
		pInfo->Rows[pInfo->nMapNameCount-1] = nRowPos;

		/* check collision */
		for(i=0; i<pInfo->nMapNameCount-1; ++i){
			if( (pInfo->Cols[i] == nColPos) && (pInfo->Rows[i] == nRowPos) ){
				fprintf(stderr, "map position collision %s\n", szFile);
			}
		}
	}
	free_zuyou_data(pZuyou);
	return 0;
}

void CreateKiban2SVGProcessingInfo(KIBAN2SVG_PROCESSING_INFO_DATA *pInfo, const char *szKibanPathName)
{
	memset(pInfo,0,sizeof(KIBAN2SVG_PROCESSING_INFO_DATA));
	strcpy(pInfo->szKibanPath, szKibanPathName);
	EnumDirNames(szKibanPathName, GetMaxMapRectProc, (long)pInfo);
	EnumDirNames(szKibanPathName, CreateInfoFileProc, (long)pInfo);
}

int CreateMiddleFile(const char *szOutFileName, const char *szKibanPathName){
	KIBAN2SVG_PROCESSING_INFO_DATA info;
	FILE *fp;
	memset(&info,'\0',sizeof(KIBAN2SVG_PROCESSING_INFO_DATA));
	strcpy(info.szKibanPath, szKibanPathName);
	
	EnumDirNames(szKibanPathName, GetMaxMapRectProc, (long)&info);
	EnumDirNames(szKibanPathName, CreateInfoFileProc, (long)&info);
	
	fp = fopen(szOutFileName, "w");
	if(!fp)
		return ID_ERR_FILE_OPEN;
	fwrite(&info, sizeof(KIBAN2SVG_PROCESSING_INFO_DATA),1,fp);
	fclose(fp);
	return ID_ERR_NOERROR;
}


int LoadMiddleFile(const char *szInputFileName, KIBAN2SVG_PROCESSING_INFO_DATA *pInfo){
	FILE *fp;
	memset(pInfo,'\0',sizeof(KIBAN2SVG_PROCESSING_INFO_DATA));
	fp = fopen(szInputFileName, "r");
	if(!fp){
		pInfo = NULL;
		return ID_ERR_FILE_OPEN;
	}
	fread(pInfo, sizeof(KIBAN2SVG_PROCESSING_INFO_DATA), 1, fp);
	fclose(fp);
	return ID_ERR_NOERROR;
}

void PrintConnectableArcGroupXL(FILE *fp, V_LIST *pJoinArcsList){
	int name_id=1;
	V_LIST *pJoinArcs;
	ARC_ID_RECORD *pRecord;
	if(pJoinArcsList==NULL)
		return;

	for(pJoinArcsList = vl_Front(pJoinArcsList);
		pJoinArcsList;
		pJoinArcsList = pJoinArcsList->pNext){
		pJoinArcs = (V_LIST *)(pJoinArcsList->Data);
		pJoinArcs = vl_Front(pJoinArcs);
		if(!pJoinArcs->pNext)
			continue;
		fprintf(fp, "<group name=\"group_%d\">", name_id++);
		for(;pJoinArcs;pJoinArcs = pJoinArcs->pNext){
			pRecord = (ARC_ID_RECORD *)pJoinArcs->Data;
			fprintf(fp, "%s_%d ", pRecord->code, pRecord->id);
		}
		fprintf(fp, "</group>\n");
	}
}
			
int main(int argc, char* argv[])
{
	PAIR_TREE *IDTree=NULL;
	PAIR_TREE *KasenIDTree=NULL;
	
	char szKibanDataRootPath[MAX_PATH];
	char szOutputRootPath[MAX_PATH];
	char szConfFileName[MAX_PATH];
	
	KIBAN2SVG_PROCESSING_INFO_DATA info;
	int i;
	
#ifdef _DEBUG
/*	ToFullPath(szKibanDataRootPath, "cdroms\\test");
	ToFullPath(szOutputRootPath, "out");
*/
	ToFullPath(szKibanDataRootPath, 
		"C:\\MyDocuments\\gbs\\Kiban2SVG\\cdrom");
	ToFullPath(szOutputRootPath, 
		"C:\\MyDocuments\\gbs\\Kiban2SVG\\out");
	ToFullPath(szConfFileName, "kiban2svg.conf");
	argc = 4;
#else
	if(argc < 3){
		printf("usage: kiban2svg source_dataroot_path output_path [configure_filename]\n");
		return 0;
	}
	ToFullPath(szKibanDataRootPath, argv[1]);
	ToFullPath(szOutputRootPath, argv[2]);
	if(argc >= 4)
		ToFullPath(szConfFileName, argv[3]);
	else
		szConfFileName[0]='\0';
#endif
	
	if(argc >= 4){
		FILE *fp;
		fp = fopen(szConfFileName, "r");
		if(!fp){
			fprintf(stderr, "::error can not open configure file\n");
			return 0;
		}
		LoadConfigure(fp);
		fclose(fp);
	}
	
	SetPathDevider(szKibanDataRootPath);
	SetPathDevider(szOutputRootPath);
	MakeDirectory(szOutputRootPath);
	
	/* preprocess */
	CreateKiban2SVGProcessingInfo(&info, szKibanDataRootPath);
	if(info.nMapNameCount == 0){
		fprintf(stderr, "can not load source files. from ...\n%s\n", szKibanDataRootPath);
		return 1;
	}
	printf("map count is : %d\n", info.nMapNameCount);
	
	/* print arcs */
	{
		char *OutputFileNames[] = {"road","kokudou","tetudou"};
		int OutputIDs[] = {ID_ROAD,ID_KOKUDOU,ID_TETUDOU};
		char szOutputPath[MAX_PATH];
		char szOutputFile[MAX_PATH];
		for(i=0;i<3;++i){
			MAP_MATRIX *pMatrix;
			int nNewPolygonID=0;
			FILE *fpSVG;
			FILE *fpXML;
			V_LIST *pJoinArcsList=NULL;
			printf("processing %s data...\n", OutputFileNames[i]);
			pMatrix = MMCreate(szKibanDataRootPath, OutputIDs[i], &info);
			
			UniqeArcIDInMatrix(pMatrix);
			
			FindJoinArcsInMatrix(pMatrix, &pJoinArcsList);
			
			sprintf(szOutputPath, "%s%s", szOutputRootPath, OutputFileNames[i]);
			
			/* open svg file */
			sprintf(szOutputFile, "%s.svg", szOutputPath);
			fpSVG = fopen(szOutputFile,"w");
			if(!fpSVG){
				printf("::file open error file:%s\n", szOutputFile);
				continue;
			}
			printf("writing %s\n", szOutputFile);
			PrintXMLHeader(fpSVG,"UTF-8");
			PrintSVGHeader(fpSVG, 400, 400, &(info.rAllMap));
			
			/*
			鉄道の場合は、アークが入っているファイルがその他のアークと入り混じっているので、
			idの先頭が"L2300"でないアークを取り除く
			*/
			if(OutputIDs[i] == ID_TETUDOU)
				RemoveArcFromMatrixById(pMatrix, "L2300");
			
			/* output arcdata */
			ArcData2SVGInMatrix(fpSVG, pMatrix, LineColorTable[OutputIDs[i]]);
			
			/* output svg footer */
			PrintSVGFooter(fpSVG);
			fclose(fpSVG);
			
			/* open xml file */
			sprintf(szOutputFile, "%s.xml", szOutputPath);
			fpXML = fopen(szOutputFile,"w");
			if(!fpXML){
				printf("::file open error file:%s\n", szOutputFile);
				continue;
			}
			printf("writing %s\n", szOutputFile);
			PrintXMLHeader(fpXML, "Shift_JIS");
			fprintf(fpXML,"<gbs>\n");
			AttrData2XMLInMatrix(fpXML, pMatrix); 
			
		/*	PrintConnectableArcGroupXL(fpXML, pJoinArcsList); */

			fprintf(fpXML,"</gbs>\n");
			fclose(fpXML);
			
			free_map_matrix(pMatrix);
		}
	}

	/* print polygons */
	{
		char *OutputFileNames[8] = {"si_tyo","tyome","gaiku","kasen","zyouti","mizu","tatemono"};
		int OutputIDs[8] = {ID_SI_TYO, ID_TYOME, ID_GAIKU, ID_KASEN, ID_ZYOUTI, ID_MIZU, ID_TATEMONO};
		char szOutputPath[MAX_PATH];
		char szOutputFile[MAX_PATH];
		for(i=0;i<7;++i){
			MAP_MATRIX *pMatrix=NULL;
			POLY_DATA *pPoly=NULL;
			ATTR_DATA *pAttr=NULL;
			FILE *fp;
			
			printf("processing %s data...\n", OutputFileNames[i]);
			pMatrix = MMCreate(szKibanDataRootPath, OutputIDs[i], &info);
			
			JoinPolyInMatrix(pMatrix, &pPoly, &pAttr);
			sprintf(szOutputPath,"%s%s",szOutputRootPath,OutputFileNames[i]);
			
			sprintf(szOutputFile, "%s.svg", szOutputPath);
			fp = fopen(szOutputFile,"w");
			if(!fp){
				printf("::file open error file:%s\n", szOutputFile);
				continue;
			}
			printf("writing %s\n", szOutputFile);
			PrintXMLHeader(fp,"UTF-8");
			PrintSVGHeader(fp, 400, 400, &(info.rAllMap));
			Poly2SVG(fp, NULL, pPoly, FillColorTable[OutputIDs[i]], LineColorTable[OutputIDs[i]]);
			PrintSVGFooter(fp);
			fclose(fp);
			
			sprintf(szOutputFile, "%s.xml", szOutputPath);
			fp = fopen(szOutputFile,"w");
			if(!fp){
				printf("::file open error file:%s\n", szOutputFile);
				continue;
			}
			printf("writing %s\n", szOutputFile);
			
			PrintXMLHeader(fp, "Shift_JIS");
			fprintf(fp,"<gbs>\n");
			Attr2XML(fp,pAttr);
			fprintf(fp,"</gbs>\n");
			fclose(fp);
			free_poly_data(pPoly);
			free_attr_data(pAttr);
			free_map_matrix(pMatrix);
		}
	}
	return 0;
}



/* html print funcs. not used now.
#include "windows.h"
int MapRoot2HTMLFile(const char *szMapRootPath, const char *szHTMLFile){
	int nRetCode;

	char szTemp[MAX_PATH];
	char szName[64];
	ZUYOU_DATA *pData;
	FILE *fp;
	GB_POINT positions[9] = {{300,0},{300,200},{300,400},
							{150,400},{0,400},{0,200},
							{0,0},{150,0},{150,200}};
	char szFileName[32];
	char szLinkName[32];
	int i;


	ExtractFileName(szMapRootPath, szName);
	sprintf(szTemp, "%s%s.txt", szMapRootPath, szName);

	nRetCode = ReadZuyouDataFile(szTemp,&pData);
	if(nRetCode != ID_ERR_NOERROR){
		return nRetCode;
	}
	
	fp = fopen(szHTMLFile, "w");
	if(!fp){
		free_zuyou_data(pData);
		return ID_ERR_FILE_OPEN;
	}
	
	fprintf(fp,"<HTML><HEAD>"
		"<STYLE type=\"text/css\">"
		"div {position:absolute; width:150; height:200; }"
		"</STYLE>");
	fprintf(fp,"<SCRIPT LANGUAGE=\"JavaScript\" src=\"draganddrop.js\">"
				"</SCRIPT></HEAD><BODY onLoad=\"dragLayer()\">");
	for(i=0;i<9;++i){
		if(i == 8){
			sprintf(szFileName,"%s.svg",szName);
			sprintf(szLinkName,"%s.xml",szName);
		}
		else{
			sprintf(szFileName, "%s.svg", pData->pszSurroundMapNames[i]);
			sprintf(szLinkName,"%s.html", pData->pszSurroundMapNames[i]);
		}
		
		fprintf(fp, "<DIV style='left:%f; top:%f;'>", 
			positions[i].x, positions[i].y);
		fprintf(fp, "□□□□□□□<EMBED WIDTH=150 HEIGHT=200 SRC=\"%s\">", szFileName);
		fprintf(fp, "</DIV>");
	}
	fprintf(fp, "<DIV style='left:450; top:300;'>"
				"<A HREF=\"%s.xml\" target=\"gbswnd\">中心のSVGのXMLを表示</A></DIV>", 
				szName);
	fprintf(fp, "</BODY></HTML>");
	fclose(fp);

	free_zuyou_data(pData);
	return ID_ERR_NOERROR;
}

void Kiban2SVG(const char *szInputPath, const char *szOutputPath)
{
	//char szInputPath[MAX_PATH];
	//char szOutputPath[MAX_PATH];
	char szSVGFile[MAX_PATH];
	char szInfoFile[MAX_PATH];
	char szHTMLFile[MAX_PATH];
	char szBrouseHtml[MAX_PATH];
	char szTemp[MAX_PATH];
	
	//strcpy(szInputPath,"c:\\MyDocuments\\VC++\\Kiban2SVG\\京都CD2コンテンツ\\");
	//strcpy(szOutputPath,"c:\\MyDocuments\\VC++\\Kiban2SVG\\html\\");
	
	CreateDirectory(szOutputPath,NULL);
	
	//ディレクトリ内すべてのデータを出力する
	WIN32_FIND_DATA ffd;
	sprintf(szTemp, "%s*.*", szInputPath);
	HANDLE hFind = FindFirstFile(szTemp, &ffd);
	int nFileCounter=0;
	while(hFind){
		int nCounter = 0;
		sprintf(szBrouseHtml,"%sviewmap%03d.html", szOutputPath, nFileCounter);
		FILE *fp = fopen(szBrouseHtml,"w");
		fprintf(fp,"<HTML><HEAD>"
		"<STYLE type=\"text/css\">"
		"div { position: absolute; width:150; height:220; }"
		"</STYLE>"
		"<SCRIPT LANGUAGE=\"JavaScript\" src=\"draganddrop.js\">"
		"</SCRIPT></HEAD><BODY onLoad=\"dragLayer()\">");
		
		char szBunruiPathName[MAX_PATH];
		char szFileName[MAX_PATH];
		while(nCounter != 20){
			if(strcmp(ffd.cFileName, ".") != 0 &&
				strcmp(ffd.cFileName, "..") != 0 &&
				(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
				){
				int i=0;
				while(szFileName[i++] = tolower(ffd.cFileName[i]));

				sprintf(szSVGFile, "%s%s.svg", szOutputPath, szFileName);
				sprintf(szInfoFile, "%s%s.xml", szOutputPath, szFileName);
				sprintf(szHTMLFile, "%s%s.html", szOutputPath, szFileName);
				sprintf(szBunruiPathName, "%s%s\\", szInputPath, szFileName);
				
				MapRoot2SVGFile(szBunruiPathName, szSVGFile, szInfoFile);
				MapRoot2HTMLFile(szBunruiPathName, szHTMLFile);
				fprintf(fp, "<DIV style='left:%d; top:%d; cursor:hand;'>", (nCounter%3)*200, (nCounter/3)*220);
				fprintf(fp, "□□□□□□□□<EMBED WIDTH=150 HEIGHT=200 SRC=\"%s\">", szSVGFile);
				fprintf(fp, "</DIV>");
			}
			if(!FindNextFile(hFind, &ffd)){
				FindClose(hFind);
				hFind = NULL;
				break;
			}
			nCounter++;
			nFileCounter++;
		}
		fprintf(fp,"</BODY></HTML>");
		fclose(fp);
	}
}
*/
