import java.applet.*;
import java.awt.*;
import java.awt.event.*;



public class m0104287_kadai04 extends Applet{
	Label lbl1 = new Label ("重ね");
	TextField tf_kasane = new TextField ("1");
	Label lbl2 = new Label ("描画パターン");


	Label lb_a11 = new Label ("a_11"), lb_a12 = new Label ("a_12"), lb_a13 = new Label ("a_13");
	Label lb_a21 = new Label ("a_21"), lb_a22 = new Label ("a_22"), lb_a23 = new Label ("a_23");

	TextField tf_a11 = new TextField ("1.0"), tf_a12 = new TextField ("0.0"), tf_a13 = new TextField ("0");
	TextField tf_a21 = new TextField ("0.0"), tf_a22 = new TextField ("1.0"), tf_a23 = new TextField ("0");

   	Choice draw_pattern = new Choice ();
	Button btnDraw = new Button ("描画");

	Panel pnl_1;
	Panel pnl_2;
	int WIDTH, HEIGHT;
	int m = 200;			//曲線一本当たりの描画回数
	int iYoko , iTate;		//間隔
	int col = 0; 			//色保存
	double radio;			//長さ
	double thita;			// 回転
	double kakeX = 1.2;		//x拡大比
	double kakeY = 1.3;		//x拡大比
	double a_11 = 1.00;
	double a_12 = 0.00;
	int a_13 = 0;		//ズレ
	double a_21 = 0.00;
	double a_22 = 1.00;
	int a_23 = 0;		//ズレ
	double dKakudai = 1.3;		//重ねの拡大比
	int iW_lim = WIDTH + a_13;
	int iH_lim = HEIGHT + a_23;

	int pat = 0;
	int iKasane = Integer.parseInt(tf_kasane.getText());

	// ＋方向
	Point[] p1 = new Point[2*m];
	Point[] p2 = new Point[2*m];
	Point[] p3 = new Point[2*m];

	Point[] p4 = new Point[2*m];
	Point[] p5 = new Point[2*m];
	Point[] p6 = new Point[2*m];

	Point[] p_base = new Point[m];
	Point[] p = new Point[m];

	Point[] p_one = new Point[3];

	public void init (){
		WIDTH = 800; HEIGHT = 600;
		iYoko = 180;
		iTate = 180;
		radio = 15.0;
		thita = 45;
		setBackground(Color.white);
		setLayout (new FlowLayout ());
		add ("North", pnl_1 = new Panel());
		//setLayout (new BorderLayout ());
		add ("Center", pnl_2 = new Panel());
		draw_pattern.add ("一つだけ");
		draw_pattern.add ("鏡映変換で一つ");
		draw_pattern.add ("並べて表示");

		pnl_1.setBackground(Color.pink);
		pnl_1.setLayout(new GridLayout(2,6));
		pnl_1.add(lb_a11);		pnl_1.add(tf_a11);
		pnl_1.add(lb_a12);		pnl_1.add(tf_a12);
		pnl_1.add(lb_a13);		pnl_1.add(tf_a13);
		pnl_1.add(lb_a21);		pnl_1.add(tf_a21);
		pnl_1.add(lb_a22);		pnl_1.add(tf_a22);
		pnl_1.add(lb_a23);		pnl_1.add(tf_a23);

		pnl_2.setLayout(new GridLayout(1,6));
		pnl_2.add(lbl1);
		pnl_2.add(tf_kasane);
		pnl_2.add(lbl2);
		pnl_2.add(draw_pattern);
		pnl_2.add(btnDraw);
/*
		setLayout(new BorderLayout(3 , 1));
		add(pnl_1 , BorderLayout.NORTH);
		add(pnl_2 , BorderLayout.CENTER);
*/

		btnDraw.addActionListener (new java.awt.event.ActionListener (){
			public void actionPerformed (ActionEvent e){
				iKasane = (int)Double.parseDouble(tf_kasane.getText());

				a_11 = Double.parseDouble(tf_a11.getText());
				a_12 = -1*Double.parseDouble(tf_a12.getText());
				a_13 = (int)Double.parseDouble(tf_a13.getText());
				a_21 = Double.parseDouble(tf_a21.getText());
				a_22 = Double.parseDouble(tf_a22.getText());
				a_23 = (int)Double.parseDouble(tf_a23.getText());

				if(iKasane < 1){
					iKasane = 1;
				}
				pat = draw_pattern.getSelectedIndex ();
				draw_set ();
			}
		});
	}
	public void paint(Graphics g){
		int iW = (int)(iYoko* kakeX * Math.pow(dKakudai, iKasane - 1));
		int iH = (int)(iTate * kakeY * Math.pow(dKakudai, iKasane - 1));
		int ix_s;
		int iy_s;
		if(pat == 2){
			ix_s =  a_13;
			iy_s =  -a_23;
		}else{
			ix_s = WIDTH/2 + a_13;
			iy_s = HEIGHT/2 - a_23;
		}
		iW_lim = WIDTH + iW + a_13;
		iH_lim = HEIGHT + iH + a_23;
		int ix = ix_s;
		int iy = iy_s;
		int b = 0;
		double th_pi = thita/360 * 2.0*Math.PI;		// ラジアンに変換

		double th_pi1 = 300.0/360 * 2.0*Math.PI;
		double th_pi2 = 60.0/360 * 2.0*Math.PI;
		double th_pi3 = 180.0/360 * 2.0*Math.PI;

		for (int i=0; i < 2*m; i++){
				double ang;
				double ang2;
			if (i < m){
				ang = 2.0*Math.PI*i/(m);
				ang2 = -2.0*Math.PI*i/(m);
				p_base[i] = new Point((int)(-radio* ang *Math.sin(ang/4 + th_pi)), (int)(-radio* ang *Math.cos(ang/4 + th_pi)));

				p1[i] = new Point((int)( radio/3* ang *Math.cos(ang/4 + th_pi1)), (int)(radio/3* ang *Math.sin(ang/4 + th_pi1)));
				p2[i] = new Point((int)( radio/3* ang *Math.cos(ang/4 + th_pi2)), (int)(radio/3* ang *Math.sin(ang/4 + th_pi2)));
				p3[i] = new Point((int)( radio/3* ang *Math.cos(ang/4 + th_pi3)), (int)(radio/3* ang *Math.sin(ang/4 + th_pi3)));
			}
			else{
				ang = 2.0*Math.PI*(i-m)/(m);
				ang2 = -2.0*Math.PI*(i-m)/(m);

				p1[i] = new Point((int)( radio/3* ang2 *Math.cos(ang2/4 + th_pi1)), (int)(radio/3* ang2 *Math.sin(ang2/4 + th_pi1)));
				p2[i] = new Point((int)( radio/3* ang2 *Math.cos(ang2/4 + th_pi2)), (int)(radio/3* ang2 *Math.sin(ang2/4 + th_pi2)));
				p3[i] = new Point((int)( radio/3* ang2 *Math.cos(ang2/4 + th_pi3)), (int)(radio/3* ang2 *Math.sin(ang2/4 + th_pi3)));
			}
		}

		while(ix < iW_lim){//横方向の繰り返し
			while(iy < iH_lim){//縦方向の繰り返し

				int iRe = 1;
				if(pat != 0)
					iRe = 8;
				for(int j = 0 ; j < iRe; j++){
					int sX = 1;
					int sY = 1;		//鏡面表現用
					if(j < 2){
					}else if( j < 4){
						sY = -1;
					}else if( j < 6){
						sX = -1;
						sY = -1;
					}else{
						sX = -1;
					}

					for(int k = 1; k <= iKasane; k++){

						int iR = (int)(Math.random() * 255);
						int iG = (int)(Math.random() * 255);
						int iB = (int)(Math.random() * 255);

						g.setColor( new Color(iR, iG, iB));

						p_one[0] = new Point((int)(p_base[m - 1].x* Math.pow(dKakudai, k - 1)* a_11 + p_base[m - 1].y*Math.pow(dKakudai, k - 1)* a_12)
										,(int)(p_base[m - 1].x* Math.pow(dKakudai, k - 1)* a_21+  p_base[m - 1].y* Math.pow(dKakudai, k - 1)* a_22));

						p[0] = new Point((int)(p_base[0].x* Math.pow(dKakudai, k - 1)* a_11 + p_base[0].y*Math.pow(dKakudai, k - 1)* a_12)
										,(int)(p_base[0].x* Math.pow(dKakudai, k - 1)* a_21+  p_base[0].y* Math.pow(dKakudai, k - 1)* a_22));
						p_one[1] = new Point(sX * p[0].x, sY * p[0].y);
						p[0].x = sX * (p[0].x - p_one[0].x);
						p[0].y = sY * (p[0].y - p_one[0].y);

						p4[0] = new Point((int)(sX *p1[0].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p1[0].y* Math.pow(dKakudai, k - 1)*a_12 )
									,(int)(sX *p1[0].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p1[0].y* Math.pow(dKakudai, k - 1)* a_22));
						p5[0] = new Point((int)(sX *p2[0].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p2[0].y* Math.pow(dKakudai, k - 1)*a_12 )
									,(int)(sX *p2[0].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p2[0].y* Math.pow(dKakudai, k - 1)* a_22));
						p6[0] = new Point((int)(sX *p3[0].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p3[0].y* Math.pow(dKakudai, k - 1)*a_12 )
									,(int)(sX *p3[0].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p3[0].y* Math.pow(dKakudai, k - 1)* a_22));
						for(int i =1; i < 2*m; i++){// 位置
							if(i < m){
								p[i] = new Point((int)(p_base[i].x* Math.pow(dKakudai, k - 1)* a_11 + p_base[i].y*Math.pow(dKakudai, k - 1)* a_12)
										,(int)(p_base[i].x* Math.pow(dKakudai, k - 1)* a_21+  p_base[i].y* Math.pow(dKakudai, k - 1)* a_22));
								p[i].x  = sX * (p[i].x - p_one[0].x);
								p[i].y  = sY * (p[i].y - p_one[0].y);
								if(j % 2 < 1){
									if((p[i-1].x  + ix > 0)&&(p[i-1].y + iy > 0) && ( p[i].x + ix  > 0)&&( p[i].y + iy > 0))
										g.drawLine(p[i-1].x  + ix , p[i-1].y + iy, p[i].x + ix , p[i].y + iy);
								}else{
									if((-p[i-1].y  + ix > 0)&&(- p[i-1].x + iy > 0) && (- p[i].y + ix > 0)&&( -p[i].x + iy > 0))
										g.drawLine(-p[i-1].y  + ix ,- p[i-1].x + iy,- p[i].y + ix , -p[i].x + iy);
								}
							}
							p4[i] = new Point((int)(sX *p1[i].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p1[i].y* Math.pow(dKakudai, k - 1)*a_12 )
										,(int)(sX *p1[i].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p1[i].y* Math.pow(dKakudai, k - 1)* a_22));

							p5[i] = new Point((int)(sX *p2[i].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p2[i].y* Math.pow(dKakudai, k - 1)*a_12 )
										,(int)(sX *p2[i].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p2[i].y* Math.pow(dKakudai, k - 1)* a_22));
							p6[i] = new Point((int)(sX *p3[i].x* Math.pow(dKakudai, k - 1)* a_11 + sY *p3[i].y* Math.pow(dKakudai, k - 1)*a_12 )
										,(int)(sX *p3[i].x* Math.pow(dKakudai, k - 1)* a_21 + sY *p3[i].y* Math.pow(dKakudai, k - 1)* a_22));
							if(i != m){
								if(j % 2 < 1){
									if((p4[i - 1].x + ix + p[0].x > 0)&&(p4[i - 1].y + iy + p[0].y > 0)&&(p4[i].x + ix + p[0].x > 0)&&( p4[i].y + iy + p[0].y > 0))
										{ g.drawLine((int)(p4[i - 1].x + ix + p[0].x),(int)(p4[i - 1].y + iy + p[0].y) ,(int)(p4[i].x + ix + p[0].x) ,(int)( p4[i].y + iy + p[0].y)); }

									if((p5[i - 1].x + ix + p[0].x > 0)&&(p5[i - 1].y + iy + p[0].y > 0)&&(p5[i].x + ix + p[0].x > 0)&&( p5[i].y + iy + p[0].y > 0))
										{ g.drawLine((int)(p5[i - 1].x + ix + p[0].x),(int)(p5[i - 1].y + iy + p[0].y) ,(int)(p5[i].x + ix + p[0].x) ,(int)( p5[i].y + iy + p[0].y)); }

									if((p6[i - 1].x + ix + p[0].x > 0) && (p6[i - 1].y + iy + p[0].y > 0) && (p6[i].x + ix + p[0].x > 0)&&( p6[i].y + iy + p[0].y > 0))
										{ g.drawLine((int)(p6[i - 1].x + ix + p[0].x),(int)(p6[i - 1].y + iy + p[0].y) ,(int)(p6[i].x + ix + p[0].x) ,(int)( p6[i].y + iy + p[0].y)); }
								}else{
									if((-p4[i - 1].y + ix - p[0].y > 0) && (-p4[i - 1].x + iy - p[0].x > 0) && (-p4[i].y + ix - p[0].y > 0) && ( -p4[i].x + iy - p[0].x > 0))
										g.drawLine((int)(-p4[i - 1].y + ix - p[0].y),(int)(-p4[i - 1].x + iy - p[0].x) ,(int)(-p4[i].y + ix - p[0].y) ,(int)( -p4[i].x + iy - p[0].x));

									if((-p5[i - 1].y + ix - p[0].y> 0) && (-p5[i - 1].x + iy - p[0].x > 0) && (-p5[i].y + ix - p[0].y > 0) && ( -p5[i].x + iy - p[0].x > 0))
										g.drawLine((int)(-p5[i - 1].y + ix - p[0].y),(int)(-p5[i - 1].x + iy - p[0].x) ,(int)(-p5[i].y + ix - p[0].y) ,(int)( -p5[i].x + iy - p[0].x));

									if((-p6[i - 1].y + ix - p[0].y > 0) &&(-p6[i - 1].x + iy - p[0].x > 0) && (-p6[i].y + ix - p[0].y > 0) && ( -p6[i].x + iy - p[0].x > 0))
										g.drawLine((int)(-p6[i - 1].y + ix - p[0].y),(int)(-p6[i - 1].x + iy - p[0].x) ,(int)(-p6[i].y + ix - p[0].y) ,(int)( -p6[i].x + iy - p[0].x));
								}
							}
						}
					}
				}
				b++;
				if(pat == 2){
					if(b%2==1){
						ix -= iW/2;
					}else{
						ix += iW/2;
					}
					iy += iH;
				}else if(pat == 0 || b > iKasane){
					iy = iH_lim;
				}
			}
			if(pat == 2 && b %2 == 1){
				ix += iW/2;
			}
			b = 0;
			iy = iy_s;
			if(pat == 2){
				ix += iW;
			}else{
				ix = iW_lim;
			}
		}

	}

	void draw_set (){
		repaint ();
	}

}