#include"common.h"
#include<iostream>
#include<fstream>


extern HWND hMainWindow;

namespace Grid
{
	extern int Interval;
}


void Data::DrawModule(std::ofstream &f)
{
	vector2D v;
	POINT pnt;

	POINT upper_left_point;
	POINT lower_right_point;


	for(unsigned int i=0;i<module.size();i++)
	{
		Module &mdl=module[i];

		v=mdl.Center()+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin())+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		upper_left_point=v.toPOINT();
		v=mdl.Center()+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin())+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		lower_right_point=v.toPOINT();
		f << "<rect x=\"" << upper_left_point.x << "\" y=\"" << upper_left_point.y << "\" width=\"" << lower_right_point.x - upper_left_point.x << "\" height=\"" << lower_right_point.y - upper_left_point.y << "\" stroke=\"#000000\" fill=\"none\" />" << std::endl;

		v=mdl.Center()+DirectionVector[UP]*(mdl.GetLeftSize()-1)+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetLeftSize();i++,pnt.y+=Grid::Interval*2)
		{
			switch(mdl.GetLeft(i).GetDeviceClass())
			{
			case module_in:
				f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x+1 << "\" y=\"" << pnt.y + Grid::Interval/2 <<"\" text-anchor=\"start\">" << mdl.GetInput(mdl.GetLeft(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			case module_out:
				f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x+1 << "\" y=\"" << pnt.y +Grid::Interval/2 <<"\" text-anchor=\"start\">" << mdl.GetOutput(mdl.GetLeft(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			}
		}

		v=mdl.Center()+DirectionVector[RIGHT]*(mdl.GetUpSize()-1)+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetUpSize();i++,pnt.x-=Grid::Interval*2)
		{
			switch(mdl.GetUp(i).GetDeviceClass())
			{
			case module_in:
				f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-Grid::Interval/2 << "\" y=\"" << pnt.y+1 <<"\" text-anchor=\"start\">" << mdl.GetInput(mdl.GetUp(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			case module_out:
				f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-Grid::Interval/2 << "\" y=\"" << pnt.y+1 <<"\" text-anchor=\"start\">" << mdl.GetOutput(mdl.GetUp(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			}
		}

		v=mdl.Center()+DirectionVector[DOWN]*(mdl.GetRightSize()-1)+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetRightSize();i++,pnt.y-=Grid::Interval*2)
		{
			switch(mdl.GetRight(i).GetDeviceClass())
			{
			case module_in:
				f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-1 << "\" y=\"" << pnt.y + Grid::Interval/2 <<"\" text-anchor=\"end\">" << mdl.GetInput(mdl.GetRight(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			case module_out:
				f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-1 << "\" y=\"" << pnt.y + Grid::Interval/2 <<"\" text-anchor=\"end\">" << mdl.GetOutput(mdl.GetRight(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			}
		}

		v=mdl.Center()+DirectionVector[LEFT]*(mdl.GetDownSize()-1)+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetDownSize();i++,pnt.x+=Grid::Interval*2)
		{
			switch(mdl.GetDown(i).GetDeviceClass())
			{
			case module_in:
				f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-Grid::Interval/2 << "\" y=\"" << pnt.y-1 <<"\" text-anchor=\"end\">" << mdl.GetInput(mdl.GetDown(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			case module_out:
				f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
				f << "<text x=\"" << pnt.x-Grid::Interval/2 << "\" y=\"" << pnt.y-1 <<"\" text-anchor=\"end\">" << mdl.GetOutput(mdl.GetDown(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << std::endl;
				break;
			}
		}

		v=mdl.Center()+DirectionVector[UP]*(mdl.GetLeftSize()-1)+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetLeftSize();i++,pnt.y+=Grid::Interval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x-Grid::Interval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << std::endl;

		v=mdl.Center()+DirectionVector[RIGHT]*(mdl.GetUpSize()-1)+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetUpSize();i++,pnt.x-=Grid::Interval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y-Grid::Interval << "\" stroke=\"#000000\" />" << std::endl;

		v=mdl.Center()+DirectionVector[DOWN]*(mdl.GetRightSize()-1)+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetRightSize();i++,pnt.y-=Grid::Interval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x+Grid::Interval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << std::endl;

		v=mdl.Center()+DirectionVector[LEFT]*(mdl.GetDownSize()-1)+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin());
		pnt=v.toPOINT();
		for(int i=0;i<mdl.GetDownSize();i++,pnt.x+=Grid::Interval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y+Grid::Interval << "\" stroke=\"#000000\" />" << std::endl;
	}
}

void DrawGateRight(std::ofstream &f,vector2D p,int nIn,char *gateclass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[DOWN]*nIn;
	p2=v.toPOINT();
	f << "<rect x=\"" << p1.x << "\" y=\"" << p1.y << "\" width=\"" << Grid::Interval*2 << "\" height=\"" << p2.y-p1.y << "\" stroke=\"#000000\" fill=\"none\" />" << std::endl;
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[LEFT]*3+DirectionVector[UP]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.y+=Grid::Interval*2,p2.y+=Grid::Interval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << std::endl;
	v=p+DirectionVector[LEFT]*2+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)Grid::Interval*4/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+Grid::Interval*3/2 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << std::endl;
}

void DrawGateDown(std::ofstream &f,vector2D p,int nIn,char *gateclass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[UP]*2+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*nIn;
	p2=v.toPOINT();
	f << "<rect x=\"" << p1.x << "\" y=\"" << p1.y << "\" width=\"" << p2.x-p1.x << "\" height=\"" << Grid::Interval*2 << "\" stroke=\"#000000\" fill=\"none\" />" << std::endl;
	v=p+DirectionVector[UP]*2+DirectionVector[RIGHT]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[UP]*3+DirectionVector[RIGHT]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.x-=Grid::Interval*2,p2.x-=Grid::Interval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << std::endl;
	v=p+DirectionVector[UP]*2+DirectionVector[RIGHT]*(nIn-2);
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)Grid::Interval*4/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+Grid::Interval*3/2 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << std::endl;
}

void DrawGateLeft(std::ofstream &f,vector2D p,int nIn,char *gateclass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[UP]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*2+DirectionVector[DOWN]*nIn;
	p2=v.toPOINT();
	f << "<rect x=\"" << p1.x << "\" y=\"" << p1.y << "\" width=\"" << Grid::Interval*2 << "\" height=\"" << p2.y-p1.y << "\" stroke=\"#000000\" fill=\"none\" />" << std::endl;
	v=p+DirectionVector[RIGHT]*2+DirectionVector[DOWN]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*3+DirectionVector[DOWN]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.y-=Grid::Interval*2,p2.y-=Grid::Interval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << std::endl;
	v=p+DirectionVector[DOWN]*(nIn-1);
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)Grid::Interval*4/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+Grid::Interval*3/4 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << std::endl;
}

void DrawGateUp(std::ofstream &f,vector2D p,int nIn,char *gateclass)
{
	POINT p1,p2;
	vector2D v;
	v=p+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*nIn+DirectionVector[DOWN]*2;
	p2=v.toPOINT();
	f << "<rect x=\"" << p1.x << "\" y=\"" << p1.y << "\" width=\"" << p2.x-p1.x << "\" height=\"" << p2.y-p1.y << "\" stroke=\"#000000\" fill=\"none\" />" << std::endl;
	v=p+DirectionVector[DOWN]*2+DirectionVector[LEFT]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[DOWN]*3+DirectionVector[LEFT]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.x+=Grid::Interval*2,p2.x+=Grid::Interval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << std::endl;
	v=p+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)Grid::Interval*4/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+Grid::Interval*3/2 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << std::endl;
}

void Draw_Gate(std::ofstream &f,vector2D p,Direction d,int nIn,char *gateclass)
{
	POINT pnt;

	pnt=p.toPOINT();

	switch(d)
	{
	case RIGHT:
		DrawGateRight(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x+Grid::Interval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << std::endl;
		break;
	case DOWN:
		DrawGateDown(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y+Grid::Interval << "\" stroke=\"#000000\" />" << std::endl;
		break;
	case LEFT:
		DrawGateLeft(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x-Grid::Interval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << std::endl;
		break;
	case UP:
		DrawGateUp(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y-Grid::Interval << "\" stroke=\"#000000\" />" << std::endl;
		break;
	}
}

void Draw_Gate_With_Not(std::ofstream &f,vector2D p,Direction d,int nIn,char *gateclass)
{
	POINT pnt;
	pnt=p.toPOINT();

	Draw_Gate(f,p,d,nIn,gateclass);

	switch(d)
	{
	case RIGHT:
		f << "<circle cx=\"" << pnt.x+Grid::Interval/4 << "\" cy=\"" << pnt.y << "\" r=\"" << Grid::Interval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << std::endl;
		break;
	case DOWN:
		f << "<circle cx=\"" << pnt.x << "\" cy=\"" << pnt.y+Grid::Interval/4 << "\" r=\"" << Grid::Interval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << std::endl;
		break;
	case LEFT:
		f << "<circle cx=\"" << pnt.x-Grid::Interval/4 << "\" cy=\"" << pnt.y << "\" r=\"" << Grid::Interval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << std::endl;
		break;
	case UP:
		f << "<circle cx=\"" << pnt.x << "\" cy=\"" << pnt.y-Grid::Interval/4 << "\" r=\"" << Grid::Interval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << std::endl;
		break;
	}
}

void ClassifyOperationAndDraw(std::ofstream &f,Operation op,vector2D v,Direction d,int nIn)
{
	switch(op)
	{
	case NOT:
		Draw_Gate_With_Not(f,v,d,nIn,"P");
		break;
	case OR:
		Draw_Gate(f,v,d,nIn,"1");
		break;
	case AND:
		Draw_Gate(f,v,d,nIn,"");
		break;
	case NOR:
		Draw_Gate_With_Not(f,v,d,nIn,"1");
		break;
	case NAND:
		Draw_Gate_With_Not(f,v,d,nIn,"");
		break;
	}
}

void Data::DrawGate(std::ofstream &f)
{
	for(unsigned int i=0;i<gate.size();i++)
	{
		Gate g=gate[i];
		ClassifyOperationAndDraw(f,g.operation(),node(g.NodeOutIndex()).position()-DirectionVector[g.direction()],g.direction(),g.nIn());
	}
}

void Data::DrawConductor(std::ofstream &f)
{
	POINT p1,p2;
	for(unsigned int i=0;i<conductor.size();i++)
	{
		p1=node(conductor[i].nodeindex0()).position().toPOINT();
		p2=node(conductor[i].nodeindex1()).position().toPOINT();

		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"" << (conductor[i].isMultipath() ? "#0000ff" : "#000000") << "\" />" << std::endl;
	}
}

void Data::DrawBusIn(std::ofstream &f)
{
	for(unsigned int i=0;i<busin.size();i++)
	{
		Draw_Gate(f,node(busin[i].NodeInIndex()).position()-DirectionVector[busin[i].ReverseDirection()],busin[i].ReverseDirection(),busin[i].nOut(),"");
	}
}

void Data::DrawBusOut(std::ofstream &f)
{
	for(unsigned int i=0;i<busout.size();i++)
	{
		Draw_Gate(f,node(busout[i].NodeOutIndex()).position()-DirectionVector[busout[i].direction()],busout[i].direction(),busout[i].nIn(),"");
	}
}

void Data::DrawInputLabel(std::ofstream &f)
{
	POINT p1,p2;
	vector2D v;
	Direction d;
	for(unsigned int i=0;i<input.size();i++)
	{
		int len;
		len=lstrlen(input[i].name());
		d=input[i].direction();
		p1=(node(input[i].nodeindex()).position()-DirectionVector[input[i].direction()]).toPOINT();

		v=DirectionVector[d];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+p2.x << "\" y2=\"" << p1.y+p2.y << "\" stroke=\"" << "#000000\" />" << std::endl;
		v=DirectionVector[(d+3)%8];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+p2.x/2 << "\" y2=\"" << p1.y+p2.y/2 << "\" stroke=\"" << "#000000\" />" << std::endl;
		v=DirectionVector[(d+5)%8];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+1+p2.x/2 << "\" y2=\"" << p1.y+p2.y/2 << "\" stroke=\"" << "#000000\" />" << std::endl;

		switch(d)
		{
		case RIGHT:
			f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval << "\" y=\"" << p1.y+Grid::Interval/2 <<"\" text-anchor=\"end\">" << input[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case DOWN:
			f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval/2 << "\" y=\"" << p1.y-Grid::Interval <<"\" text-anchor=\"end\" glyph-orientation-vertical=\"90\">" << input[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case LEFT:
			f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x+Grid::Interval << "\" y=\"" << p1.y+Grid::Interval/2 <<"\" text-anchor=\"start\">" << input[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case UP:
			f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval/2 << "\" y=\"" << p1.y+Grid::Interval <<"\" text-anchor=\"start\" glyph-orientation-vertical=\"90\">" << input[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		}
	}
}

void Data::DrawOutputLabel(std::ofstream &f)
{
	POINT p1,p2;
	vector2D v;
	Direction d;
	for(unsigned int i=0;i<output.size();i++)
	{
		int len;
		len=lstrlen(output[i].name());
		d=output[i].direction();
		p1=(node(output[i].nodeindex()).position()-DirectionVector[output[i].direction()]).toPOINT();

		v=DirectionVector[d];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+p2.x << "\" y2=\"" << p1.y+p2.y << "\" stroke=\"" << "#000000\" />" << std::endl;
		v=DirectionVector[(d+1)%8];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+p2.x/2 << "\" y2=\"" << p1.y+p2.y/2 << "\" stroke=\"" << "#000000\" />" << std::endl;
		v=DirectionVector[(d+7)%8];
		p2=v.MulGridInterval();
			f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p1.x+p2.x/2 << "\" y2=\"" << p1.y+p2.y/2 << "\" stroke=\"" << "#000000\" />" << std::endl;

		switch(d)
		{
		case RIGHT:
			f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval << "\" y=\"" << p1.y+Grid::Interval/2 <<"\" text-anchor=\"end\">" << output[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case DOWN:
			f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval/2 << "\" y=\"" << p1.y-Grid::Interval <<"\" text-anchor=\"end\" glyph-orientation-vertical=\"90\">" << output[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case LEFT:
			f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x+Grid::Interval << "\" y=\"" << p1.y+Grid::Interval/2 <<"\" text-anchor=\"start\">" << output[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		case UP:
			f << "<g writing-mode=\"tb\" font-size=\"" << Grid::Interval*2-4 << "\">";
			f << "<text x=\"" << p1.x-Grid::Interval/2 << "\" y=\"" << p1.y+Grid::Interval <<"\" text-anchor=\"start\" glyph-orientation-vertical=\"90\">" << output[i].name() << "</text>";
			f << "</g>" << std::endl;
			break;
		}
	}
}

void Data::DrawNode(std::ofstream &f)
{
	Node n;
	vector2D v;
	for(unsigned int i=0;i<node_data.size();i++)
	{
		if(!node_data[i].isAllRight())
		{
			POINT p1,p2;
			n=node(i);
			p1=n.position().toPOINT();
			for(int j=0;j<8;j++)
			{
				if(n.isBranchExist((Direction)j))
				{

					v=DirectionVector[j];
					p2=v.MulGridInterval();
					p2.x=p1.x+p2.x/3;
					p2.y=p1.y+p2.y/3;
					f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"" << (node_data[i].isShort() ? "#ff0000" : "#00ff00") << "\" />" << std::endl;
				}
			}
		}
	}

	for(unsigned int i=0;i<node_data.size();i++)
	{
		POINT p1;
		n=node(i);
		p1=n.position().toPOINT();
		if(node_data[i].nBranch()>=3)
			f << "<circle cx=\"" << p1.x << "\" cy=\"" << p1.y << "\" r=\"" << 2 << "\" stroke=\"#000000\" fill=\"#000000\" />" << std::endl;
	}
}

void Data::DrawNote(std::ofstream &f)
{
	for(unsigned int i=0;i<note.size();i++)
	{
		POINT p;
		p=note[i].position().toPOINT();
		f << "<g font-size=\"" << Grid::Interval*2-4 << "\">";
		f << "<text x=\"" << p.x+Grid::Interval/2 << "\" y=\"" << p.y+Grid::Interval/4 <<"\" text-anchor=\"start\">" << note[i].name() << "</text>";
		f << "</g>" << std::endl;
	}
}

//SÄĚ`ćvfŞűÜéÍÍ
RECT Data::SpanRect()
{
	RECT rc;
	POINT pt;

	rc.bottom=0x80000000;
	rc.top=0x7fffffff;
	rc.right=0x80000000;
	rc.left=0x7fffffff;

	for(unsigned int i=0;i<module.size();i++)
	{
		Module &mdl=module[i];

		pt=(mdl.Center()+DirectionVector[UP]*(mdl.InternalHalfHeight()+mdl.UpMargin()+1)+DirectionVector[LEFT]*(mdl.InternalHalfWidth()+mdl.LeftMargin()+1)).toPOINT();
		if(pt.x<rc.left)rc.left=pt.x;
		if(pt.y<rc.top)rc.top=pt.y;
		pt=(mdl.Center()+DirectionVector[DOWN]*(mdl.InternalHalfHeight()+mdl.DownMargin()+1)+DirectionVector[RIGHT]*(mdl.InternalHalfWidth()+mdl.RightMargin()+1)).toPOINT();
		if(pt.x>rc.right)rc.right=pt.x;
		if(pt.y>rc.bottom)rc.bottom=pt.y;
	}
	for(unsigned int i=0;i<gate.size();i++)
	{
		switch(gate[i].direction())
		{
		case RIGHT:
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[LEFT]*3+DirectionVector[UP]*gate[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[DOWN]*gate[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case DOWN:
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[UP]*3+DirectionVector[LEFT]*gate[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*gate[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case LEFT:
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[UP]*gate[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*3+DirectionVector[DOWN]*gate[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case UP:
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[LEFT]*gate[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[gate[i].NodeOutIndex()].position()+DirectionVector[DOWN]*3+DirectionVector[RIGHT]*gate[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	for(unsigned int i=0;i<conductor.size();i++)
	{
		pt=node_data[conductor[i].nodeindex0()].position().toPOINT();
		if(pt.x<rc.left)rc.left=pt.x;
		if(pt.y<rc.top)rc.top=pt.y;
		if(pt.x>rc.right)rc.right=pt.x;
		if(pt.y>rc.bottom)rc.bottom=pt.y;
		pt=node_data[conductor[i].nodeindex1()].position().toPOINT();
		if(pt.x<rc.left)rc.left=pt.x;
		if(pt.y<rc.top)rc.top=pt.y;
		if(pt.x>rc.right)rc.right=pt.x;
		if(pt.y>rc.bottom)rc.bottom=pt.y;
	}
	for(unsigned int i=0;i<busin.size();i++)
	{
		switch(busin[i].direction())
		{
		case RIGHT:
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[DOWN]*busin[i].nOut()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[LEFT]*3-DirectionVector[UP]*busin[i].nOut()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case DOWN:
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[RIGHT]*busin[i].nOut()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[UP]*3-DirectionVector[LEFT]*busin[i].nOut()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case LEFT:
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[RIGHT]*3-DirectionVector[DOWN]*busin[i].nOut()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[UP]*busin[i].nOut()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case UP:
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[DOWN]*3-DirectionVector[RIGHT]*busin[i].nOut()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busin[i].NodeInIndex()].position()-DirectionVector[LEFT]*busin[i].nOut()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	for(unsigned int i=0;i<busout.size();i++)
	{
		switch(busout[i].direction())
		{
		case RIGHT:
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[LEFT]*3+DirectionVector[UP]*busout[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[DOWN]*busout[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case DOWN:
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[UP]*3+DirectionVector[LEFT]*busout[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*busout[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case LEFT:
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[UP]*busout[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[RIGHT]*3+DirectionVector[DOWN]*busout[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case UP:
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[LEFT]*busout[i].nIn()).toPOINT();
				if(pt.x<rc.left)rc.left=pt.x;
				if(pt.y<rc.top)rc.top=pt.y;
				pt=(node_data[busout[i].NodeOutIndex()].position()+DirectionVector[DOWN]*3+DirectionVector[RIGHT]*busout[i].nIn()).toPOINT();
				if(pt.x>rc.right)rc.right=pt.x;
				if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	for(unsigned int i=0;i<input.size();i++)
	{
		switch(input[i].direction())
		{
		case RIGHT:
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]*(strlen(input[i].name())+3)).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case DOWN:
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[UP]*(strlen(input[i].name())+3)+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case LEFT:
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]*(strlen(input[i].name())+3)).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case UP:
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[DOWN]*(strlen(input[i].name())+3)+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	for(unsigned int i=0;i<output.size();i++)
	{
		switch(output[i].direction())
		{
		case RIGHT:
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]*(strlen(output[i].name())+3)).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case DOWN:
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[UP]*(strlen(output[i].name())+3)+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case LEFT:
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]*(strlen(output[i].name())+3)).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		case UP:
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]).toPOINT();
			if(pt.x<rc.left)rc.left=pt.x;
			if(pt.y<rc.top)rc.top=pt.y;
			pt=(node_data[output[i].nodeindex()].position()+DirectionVector[DOWN]*(strlen(output[i].name())+3)+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	for(unsigned int i=0;i<note.size();i++)
	{
		pt=(note[i].position()+DirectionVector[UP]+DirectionVector[LEFT]).toPOINT();
		if(pt.x<rc.left)rc.left=pt.x;
		if(pt.y<rc.top)rc.top=pt.y;
		pt=(note[i].position()+DirectionVector[DOWN]+DirectionVector[RIGHT]*(strlen(note[i].name())+3)).toPOINT();
		if(pt.x>rc.right)rc.right=pt.x;
		if(pt.y>rc.bottom)rc.bottom=pt.y;
	}

	rc.bottom+=Grid::Interval;
	rc.left-=Grid::Interval;
	rc.right+=Grid::Interval;
	rc.top-=Grid::Interval;
	return rc;
}

void Data::Draw(std::ofstream &f)
{
	char s[256];
	RECT rc;
	f << "<?xml version=\"1.0\" encoding=\"Shift-JIS\"?>" << std::endl;
	rc=SpanRect();
	sprintf_s(s,sizeof(s),"%d %d %d %d",rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top);
	f << "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"" << s << "\">" << std::endl;
	DrawModule(f);
	DrawGate(f);
	DrawConductor(f);
	DrawBusIn(f);
	DrawBusOut(f);
	DrawInputLabel(f);
	DrawOutputLabel(f);
	DrawNode(f);
	DrawNote(f);
	f << "</svg>" << std::endl;
}

bool SaveSVG(Data d)
{
	OPENFILENAME ofn;
	char szFile[MAX_PATH]="";
	char szFileTitle[MAX_PATH]="";

	memset(&ofn,0,sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hMainWindow;
	ofn.lpstrFilter = TEXT("SVG(*.svg)\0*.svg\0\0");
	ofn.lpstrFile = szFile;
	ofn.lpstrFileTitle = szFileTitle;
	ofn.nFilterIndex = 1;
	ofn.nMaxFile = MAX_PATH;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
	ofn.lpstrDefExt = TEXT("svg");
	ofn.lpstrTitle = TEXT("SVG`ŽĹńH}đoÍ");

	if(GetSaveFileName(&ofn) == 0) return false;

	std::ofstream f(szFile);
	d.Draw(f);
	f.close();
	return true;
}
