// *******************************************************
// *          コンピュータグラフィックス
// *   レポート課題1-a: 「アフィン変換」」
// *------------------------------------------------------
// *               57710  大木 信道
// *         "Affine.java"
// *******************************************************

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/*=============================================
 *       "Affineクラス"
 *     アフィン変換アプレット
 *============================================*/
public class Affine extends Applet
{
    AffControls controls;
    AffCanvas canvas;

/*------初期化:レイアウト-----*/
public void init()
    {
	setLayout(new BorderLayout());
	canvas = new AffCanvas();
	add("Center", canvas);
	add("South", controls = new AffControls(canvas));
    }
}

/*=================================================
 *         "AffCanvasクラス"
 *   図形を描画するキャンバスクラス
 *================================================*/
class AffCanvas extends Canvas
{
    Rectangle r = new Rectangle(300, 350);
    Point[] point = new Point[4];     //変換前の点
    Point[] point_1 = new Point[4]; //変換後の点
    static double[][] parameter = {{1.0,0.0,0.0},{0.0,1.0,0.0}};
    
/*-------AffCanvasのコンストラクタ--------*/
public AffCanvas()
    {
	for(int i = 0; i < 4; i++)
	    point[i] = new Point();
	for(int i = 0; i < 4; i++)
	    point_1[i] = new Point();
	
	point[0].x = 0;
	point[0].y = 0;
	point[1].x = 0;
	point[1].y = 30;
	point[2].x = 30;
	point[2].y = 30;
	point[3].x = 30;
	point[3].y = 0;
    }
    
/*----------ペイント処理関数---------*/
public void paint(Graphics g)
    {
	setBackground(Color.white);
	g.setColor(Color.gray);
	g.drawRect(0, 0, r.width, r.height);
	
	g.setColor(Color.red);
	g.drawLine(0, r.height / 2, r.width, r.height / 2);
	g.drawLine(r.width / 2, 0, r.width / 2, r.height);
	
	affine_change();
	
	g.setColor(Color.blue);
	for(int i = 0; i < 4; i++)
	    g.drawLine(point_1[i].x + r.width / 2, r.height / 2 - point_1[i].y,
                       point_1[(i+1)%4].x + r.width / 2, r.height / 2 -
		       point_1[(i+1)%4].y);

	upload_model();
    }
    
    /*--------アフィン変換関数----------*/
    void affine_change()
    {
	for(int i = 0; i < 4; i++)
	    {
		
		point_1[i].x = (int)(parameter[0][0]*point[i].x +
		    parameter[0][1]*point[i].y +
		    parameter[0][2]*1);

		point_1[i].y = (int)(parameter[1][0]*point[i].x +
		    parameter[1][1]*point[i].y +
		    parameter[1][2]*1);
	    }
    }

    /*-----点を更新する関数-------*/
    void upload_model()
    {
	for(int i = 0; i < 4; i++){
	    point[i].x = point_1[i].x;
	    point[i].y = point_1[i].y;
	}
    }

/*------図形をリセットする関数---------*/
public void reset_model()
    {
	point[0].x = 0;
	point[0].y = 0;
	point[1].x = 0;
	point[1].y = 30;
	point[2].x = 30;
	point[2].y = 30;
	point[3].x = 30;
	point[3].y = 0;
    }
}

/*====================================================
 *           "AffControlsクラス"
 *     パネルの制御をするクラス
 *===================================================*/
class AffControls extends Panel implements ActionListener
{
    TextField[][] tf = new TextField[2][3];
    AffCanvas canvas;
    Panel p = new Panel();
    Panel p1 = new Panel();
    
/*---------AffControlsのコンストラクタ----------*/
public AffControls(AffCanvas canvas)
    {
	Button b = null;
	this.canvas = canvas;

	p.setLayout(new GridLayout(2,6));

	p.add(new Label("a11"));
	p.add(tf[0][0] = new TextField("1", 3));
	p.add(new Label("a12"));
	p.add(tf[0][1] = new TextField("0", 3));
	p.add(new Label("a13"));
	p.add(tf[0][2] = new TextField("0", 3));
	p.add(new Label("a21"));
	p.add(tf[1][0] = new TextField("0", 3));
	p.add(new Label("a22"));
	p.add(tf[1][1] = new TextField("1", 3));
	p.add(new Label("a23"));
	p.add(tf[1][2] = new TextField("0", 3));
	
	b = new Button("Change");
	b.addActionListener(this);
	p1.add(b);
	b = new Button("Defaults");
	b.addActionListener(this);
	p1.add(b);
	
	setLayout(new BorderLayout());
	add("Center", p);
	add("South", p1);
    }
    
/*--------ボタンイベントを処理する関数-----------*/
public void actionPerformed(ActionEvent ev)
    {
	String label = ev.getActionCommand();
	
	if(label.equals("Defaults"))
	    {
		canvas.reset_model();
		
		AffCanvas.parameter[0][0] = 1;
		AffCanvas.parameter[0][1] = 0;
		AffCanvas.parameter[0][2] = 0;
		AffCanvas.parameter[1][0] = 0;
		AffCanvas.parameter[1][1] = 1;
		AffCanvas.parameter[1][2] = 0;
	    }
	else if(label.equals("Change"))
	    {
     for(int i = 0; i < 2; i++)
	 for(int j = 0; j < 3; j++)
	     AffCanvas.parameter[i][j] = 
		 Double.valueOf(tf[i][j].getText()).doubleValue();
	    }
	canvas.repaint();
    }
}
