#include<iostream>
#include<fstream>

#include"common.h"

extern int GridInterval;

void Data::DrawModule(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\" />" << 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+=GridInterval*2)
		{
			switch(mdl.GetLeft(i).GetDeviceClass())
			{
			case module_in:
				f << "<g font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x+1 << "\" y=\"" << pnt.y <<"\" text-anchor=\"start\">" << mdl.GetInput(mdl.GetLeft(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << endl;
				break;
			case module_out:
				f << "<g font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x+1 << "\" y=\"" << pnt.y <<"\" text-anchor=\"start\">" << mdl.GetOutput(mdl.GetLeft(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << 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-=GridInterval*2)
		{
			switch(mdl.GetUp(i).GetDeviceClass())
			{
			case module_in:
				f << "<g writing-mode=\"tb\" font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-GridInterval/2 << "\" y=\"" << pnt.y+1 <<"\" text-anchor=\"start\">" << mdl.GetInput(mdl.GetUp(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << endl;
				break;
			case module_out:
				f << "<g writing-mode=\"tb\" font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-GridInterval/2 << "\" y=\"" << pnt.y+1 <<"\" text-anchor=\"start\">" << mdl.GetOutput(mdl.GetUp(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << 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-=GridInterval*2)
		{
			switch(mdl.GetRight(i).GetDeviceClass())
			{
			case module_in:
				f << "<g font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-1 << "\" y=\"" << pnt.y <<"\" text-anchor=\"end\">" << mdl.GetInput(mdl.GetRight(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << endl;
				break;
			case module_out:
				f << "<g font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-1 << "\" y=\"" << pnt.y <<"\" text-anchor=\"end\">" << mdl.GetOutput(mdl.GetRight(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << 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+=GridInterval*2)
		{
			switch(mdl.GetDown(i).GetDeviceClass())
			{
			case module_in:
				f << "<g writing-mode=\"tb\" font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-GridInterval/2 << "\" y=\"" << pnt.y-1 <<"\" text-anchor=\"end\">" << mdl.GetInput(mdl.GetDown(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << endl;
				break;
			case module_out:
				f << "<g writing-mode=\"tb\" font-size=\"" << GridInterval-2 << "\">";
				f << "<text x=\"" << pnt.x-GridInterval/2 << "\" y=\"" << pnt.y-1 <<"\" text-anchor=\"end\">" << mdl.GetOutput(mdl.GetDown(i).GetDeviceIndex()).name() << "</text>";
				f << "</g>" << 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+=GridInterval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x-GridInterval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << 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-=GridInterval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y-GridInterval << "\" stroke=\"#000000\" />" << 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-=GridInterval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x+GridInterval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << 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+=GridInterval*2)
			f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y+GridInterval << "\" stroke=\"#000000\" />" << endl;
	}
}

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

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

void DrawGateLeft(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]+DirectionVector[DOWN]*nIn;
	p2=v.toPOINT();
	f << "<rect x=\"" << p1.x << "\" y=\"" << p1.y << "\" width=\"" << GridInterval << "\" height=\"" << p2.y-p1.y << "\" stroke=\"#000000\" fill=\"none\" />" << endl;
	v=p+DirectionVector[RIGHT]+DirectionVector[DOWN]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[RIGHT]*2+DirectionVector[DOWN]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.y-=GridInterval*2,p2.y-=GridInterval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << endl;
	v=p+DirectionVector[DOWN]*(nIn-1);
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)GridInterval*2/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+GridInterval*3/4 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << endl;
}

void DrawGateUp(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];
	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\" />" << endl;
	v=p+DirectionVector[DOWN]+DirectionVector[LEFT]*(nIn-1);
	p1=v.toPOINT();
	v=p+DirectionVector[DOWN]*2+DirectionVector[LEFT]*(nIn-1);
	p2=v.toPOINT();
	for(int i=0;i<nIn;i++,p1.x+=GridInterval*2,p2.x+=GridInterval*2)
		f << "<line x1=\"" << p1.x << "\" y1=\"" << p1.y << "\" x2=\"" << p2.x << "\" y2=\"" << p2.y << "\" stroke=\"#000000\" />" << endl;
	v=p+DirectionVector[LEFT]*nIn;
	p1=v.toPOINT();
	f << "<g font-size=\"" << (double)GridInterval*2/strlen(gateclass) << "\">";
	f << "<text x=\"" << p1.x << "\" y=\"" << p1.y+GridInterval*3/4 <<"\" text-anchor=\"start\">" << gateclass << "</text>";
	f << "</g>" << endl;
}

void Draw_Gate(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+GridInterval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << endl;
		break;
	case DOWN:
		DrawGateDown(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y+GridInterval << "\" stroke=\"#000000\" />" << endl;
		break;
	case LEFT:
		DrawGateLeft(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x-GridInterval << "\" y2=\"" << pnt.y << "\" stroke=\"#000000\" />" << endl;
		break;
	case UP:
		DrawGateUp(f,p,nIn,gateclass);
		f << "<line x1=\"" << pnt.x << "\" y1=\"" << pnt.y << "\" x2=\"" << pnt.x << "\" y2=\"" << pnt.y-GridInterval << "\" stroke=\"#000000\" />" << endl;
		break;
	}
}

void Draw_Gate_With_Not(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+GridInterval/4 << "\" cy=\"" << pnt.y << "\" r=\"" << GridInterval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << endl;
		break;
	case DOWN:
		f << "<circle cx=\"" << pnt.x << "\" cy=\"" << pnt.y+GridInterval/4 << "\" r=\"" << GridInterval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << endl;
		break;
	case LEFT:
		f << "<circle cx=\"" << pnt.x-GridInterval/4 << "\" cy=\"" << pnt.y << "\" r=\"" << GridInterval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << endl;
		break;
	case UP:
		f << "<circle cx=\"" << pnt.x << "\" cy=\"" << pnt.y-GridInterval/4 << "\" r=\"" << GridInterval/4 << "\" stroke=\"#000000\" fill=\"#ffffff\" />" << endl;
		break;
	}
}

void ClassifyOperationAndDraw(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(ofstream &f)
{
	for(unsigned int i=0;i<gate.size();i++)
	{
		Gate g=gate[i];
		ClassifyOperationAndDraw(f,g.operation(),GetNodeCoordinate(g.NodeOutIndex())-DirectionVector[g.direction()],g.direction(),g.nIn());
	}
}

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

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

void Data::DrawInputLabel(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=(GetNodeCoordinate(input[i].nodeindex())-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\" />" << 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\" />" << 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\" />" << endl;

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

void Data::DrawOutputLabel(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=(GetNodeCoordinate(output[i].nodeindex())-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\" />" << 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\" />" << 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\" />" << endl;

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

void Data::DrawNode(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") << "\" />" << 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\" />" << 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<input.size();i++)
	{
		switch(input[i].direction())
		{
		case RIGHT:
			pt=(node_data[input[i].nodeindex()].position()+DirectionVector[UP]+DirectionVector[LEFT]*(strlen(input[i].name())/2+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())/2+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())/2+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())/2+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())/2+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())/2+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())/2+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())/2+3)+DirectionVector[RIGHT]).toPOINT();
			if(pt.x>rc.right)rc.right=pt.x;
			if(pt.y>rc.bottom)rc.bottom=pt.y;
			break;
		}
	}
	rc.bottom+=GridInterval;
	rc.left-=GridInterval;
	rc.right+=GridInterval;
	rc.top-=GridInterval;
	return rc;
}

void Data::Draw(ofstream &f)
{
	char s[256];
	RECT rc;
	f << "<?xml version=\"1.0\" encoding=\"Shift-JIS\"?>" << 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 << "\">" << endl;
	DrawModule(f);
	DrawGate(f);
	DrawConductor(f);
	DrawInputLabel(f);
	DrawOutputLabel(f);
	DrawNode(f);
	f << "</svg>" << endl;
}

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

	memset(&ofn,0,sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hwnd;
	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;

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