/******************************************************************************
 * Predmet: technologie java
 * Zadanie: zakladne 2D a 3d transformavcie
 * Dodefinovanie zadania: vytvorte program, ktory bude prezentovat zakladne
 * 			  2D a 3D transormacie
 * Autor: Patrik Bona <bona@intrak.sk>
 * Kosice dna 12.12.2001
 * poznamka: dany applet (aplikacia) reprezenruje 3D transformacie
 ******************************************************************************/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.net.URL;

public class Graph3D extends JApplet implements ActionListener {
	
	// deklaracie potrebnych objektov (tlacitka, toolbar...)
	private AnimPanel animPanel;
	private JRadioButton xButton, yButton, zButton;
	private JButton otocButton, zvacsButton, zmensButton, skosButton, spatneSkosenieButton, vlavoButton, vpravoButton, zrkadlenieButton;
	private JToolBar toolBar;
	private JLabel text;
	private ImageIcon img;
	private ButtonGroup group;
	private JPanel panel;
	
	static boolean isApplet = true;
	private boolean rozmer3d = false;
	private boolean osX = true, osY = false, osZ = false;
	
	protected Transform3D transform = new Transform3D(); // trieda obsahujuca transformacie
	
	double[][] matvrch = {{10,10,10}, // suradnice vrcholov pre 3D
			{10,10,50},
			{10,50,10},
			{10,50,50},
			{50,10,10},
			{50,10,50},
			{50,50,10},
			{50,50,50},};
	
	int[][] matsusednych = {{0,1}, // susedne vrcholy pre 3D
				{0,2},
				{0,4},
				{6,4},
				{6,7},
				{6,2},
				{5,4},
				{5,1},
				{5,7},
				{3,1},
				{3,7},
				{3,2}};

	public void init() {
		setContentPane(vytvorFormu());
	}

	public void start() {
	}
	
	public void stop() {
	}
	
	private Container vytvorFormu() { // vytvorime vzhlad appletu (aplikacie)
 
		// definicie tlacitok
		img = new ImageIcon(getURL("pics/sipkavlavo.png"));
                vlavoButton = new JButton(img);
                vlavoButton.setToolTipText("zmensi polohu vzhladom na vybranu os");
                vlavoButton.setActionCommand("POSUNMINUS");
                vlavoButton.addActionListener(this);
                
		img = new ImageIcon(getURL("pics/sipkavpravo.png"));
                vpravoButton = new JButton(img);
		vpravoButton.setToolTipText("zvacsi polohu vzhladom na vybranu os");
		vpravoButton.setActionCommand("POSUNPLUS");
		vpravoButton.addActionListener(this);
				
		img = new ImageIcon(getURL("pics/otocenie.png"));
		otocButton = new JButton(img);
		otocButton.setToolTipText("otoc objekt okolo vybranej osi (uhol = 10 st.)");
		otocButton.setActionCommand("OTOC");
		otocButton.addActionListener(this);
		
		img = new ImageIcon(getURL("pics/zvacs.png"));
		zvacsButton = new JButton(img);
		zvacsButton.setToolTipText("zvacsi objekt (M=1.1)");
		zvacsButton.setActionCommand("ZVACS");
		zvacsButton.addActionListener(this);
		
		img = new ImageIcon(getURL("pics/zmensi.png"));
		zmensButton = new JButton(img);
                zmensButton.setToolTipText("zmensi objekt (M=0.9)");
                zmensButton.setActionCommand("ZMENS");
                zmensButton.addActionListener(this);
						
		img = new ImageIcon(getURL("pics/skosenie.png"));
		skosButton = new JButton(img);
		skosButton.setToolTipText("skos objekt vzhladom na nevybrane osi (S=1)");
		skosButton.setActionCommand("SKOS");
		skosButton.addActionListener(this);

		img = new ImageIcon(getURL("pics/spatneskosenie.png"));
		spatneSkosenieButton  = new JButton(img);
		spatneSkosenieButton.setToolTipText("skos objekt vzhladom na vybranu os (S=-1)");
		spatneSkosenieButton.setActionCommand("SKOSSPATNE");
		spatneSkosenieButton.addActionListener(this);

		img = new ImageIcon(getURL("pics/zrkadlenie.png"));
		zrkadlenieButton = new JButton(img);
		zrkadlenieButton.setToolTipText("odzrkadli objekt vzhladom na vybranu os");
		zrkadlenieButton.setActionCommand("ZRKADLENIE");
		zrkadlenieButton.addActionListener(this);
		
		// nejaky ten textik
		text = new JLabel(" Vyber si os: ");
		
		xButton = new JRadioButton("x");
		xButton.setSelected(true);
		xButton.setToolTipText("vyber os x");
		xButton.setActionCommand("OSX");
		xButton.addActionListener(this);
		
		yButton = new JRadioButton("y");
		yButton.setToolTipText("vyber os y");
		yButton.setActionCommand("OSY");
		yButton.addActionListener(this);

		zButton = new JRadioButton("z");
		zButton.setToolTipText("vyber oz z");
		zButton.setActionCommand("OSZ");
		zButton.addActionListener(this);

		// zoskupenie radio buttonov
		group = new ButtonGroup();
		group.add(xButton);
		group.add(yButton);
		group.add(zButton);

		// toolbar s tlacitkami
		toolBar = new JToolBar();
                toolBar.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(" 3D tools "), BorderFactory.createEmptyBorder(5,5,5,5)));
                toolBar.add(vlavoButton);
		toolBar.add(vpravoButton);
		toolBar.add(otocButton);
                toolBar.add(zvacsButton);
                toolBar.add(zmensButton);
                toolBar.add(skosButton);
		toolBar.add(spatneSkosenieButton);
		toolBar.add(zrkadlenieButton);
		toolBar.add(text);
		toolBar.add(xButton);
		toolBar.add(yButton);
		toolBar.add(zButton);

		// panel kam sa vykresluje
		animPanel = new AnimPanel();
		animPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(" 3D draw panel "), BorderFactory.createEmptyBorder(5,5,5,5)));

		// celkovy panel kam secko nahadzeme
		panel = new JPanel(new BorderLayout());
		panel.add(toolBar,BorderLayout.NORTH);
		panel.add(animPanel,BorderLayout.CENTER);
		return panel;
	}	

	private int akaOs() {
		if(osX) return 0;
		else if(osY) return 1;
		else return 2;
	}
	
	// tu pocuvame udalosti (pre stlacanie tlacitok)
	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand().equals("OTOC")) {
			if(osX) {
				transform.otoc(10, matvrch, 0);
			}
			else if(osY) {
				transform.otoc(10, matvrch, 1);
			}
			else if(osZ) {
				transform.otoc(10, matvrch, 2);
			}
		}
		if(e.getActionCommand().equals("ZVACS")) {
			transform.zmenMierku(1.1,matvrch);
		}
		if(e.getActionCommand().equals("ZMENS")) {
			transform.zmenMierku(0.9,matvrch);
		}
		if(e.getActionCommand().equals("SKOS")) {
			transform.skos(1, akaOs(), matvrch);
		}
		if(e.getActionCommand().equals("SKOSSPATNE")) {
			transform.skos(-1, akaOs(), matvrch);
		}
		if(e.getActionCommand().equals("OSX")) {
			xButton.setSelected(true);
			osX = true;
			osY = false;
			osZ = false;
		}
		if(e.getActionCommand().equals("OSY")) {
			yButton.setSelected(true);
			osY = true;
			osX = false;
			osZ = false;
		}
		if(e.getActionCommand().equals("OSZ")) {
			zButton.setSelected(true);
			osZ = true;
			osX = false;
			osY = false;
		}
		if(e.getActionCommand().equals("POSUNMINUS")) {
			transform.posun(-10, akaOs(), matvrch);
		}
		if(e.getActionCommand().equals("POSUNPLUS")) {
			transform.posun(10, akaOs(), matvrch);
		}
		if(e.getActionCommand().equals("ZRKADLENIE")) {
			transform.odraz(akaOs(), matvrch);
		}
		animPanel.repaint();
	}
	
	// na AnimPanel sa vykresluje dany objekt ...
	private class AnimPanel extends JPanel {
		public void paintComponent(Graphics g) {
			final int alfa = 45, beta = 45, Jx = 1, Jy = 1, Jz = 1; // uhly a kektor pre axonometricke zobrazenie
			super.paintComponent(g);

			int width = size().width, height = size().height;
			// vymaz plochu
			g.clearRect(0, 0, width, height);

			// nakresli axonometricky kriz
			// kreslenie axonometrickeho kriza je len pre alfa, beta = 45 stupnov
			g.drawLine(width/2, height/2, width/2, 20);
			
			if(width/2 > height/2) {
				g.drawLine(width/2, height/2, width/2 - height/2 +10, height - 10);
				g.drawLine(width/2, height/2, width/2 + height/2 -10, height - 10);
				g.drawString("X", width/2 - height/2, height - 10); 
				g.drawString("Y", width/2 + height/2 -10, height -10);
			}
			else {
                                g.drawLine(width/2, height/2, 10, height/2 + width/2 - 10);
                                g.drawLine(width/2, height/2, width  -10, height/2 + width/2 - 10);
				g.drawString("X", 4, height/2 + width/2 -10);
				g.drawString("Y", width  -10, height/2 + width/2 - 10);
			}			
			g.drawString("Z", width/2 +5, 30);

			// vykresli objekt
			
			double[][] matvrch2D = new double[matvrch.length][2]; // pomocna matica pre transformaciu 3D -> 2D
			
			// transformovanie 3D -> 2D
			double x, y, z;
			for(int i=0;i<matvrch.length;i++) {
				x = matvrch[i][0];
				y = matvrch[i][1];
				z = matvrch[i][2];
				matvrch2D[i][0] = -Jx*transform.cosinus(alfa)*x +Jy*transform.cosinus(beta)*y;
				matvrch2D[i][1] = -Jx*transform.sinus(alfa)*x -Jy*transform.sinus(beta)*y +Jz*z;
			}

			// vykreslenie objektu			
			for(int i=0;i<matsusednych.length;i++) {
				g.drawLine(width/2 + (int)matvrch2D[matsusednych[i][0]][0], height/2 - (int)matvrch2D[matsusednych[i][0]][1], width/2 + (int)matvrch2D[matsusednych[i][1]][0], height/2 - (int)matvrch2D[matsusednych[i][1]][1]);
	                }
		}
	}


	// tato metoda je kvoli stahovaniu obrazkov v pripade appletu
	protected URL getURL(String filename) {
	        URL url = null;
                if(isApplet){
	                URL codeBase = getCodeBase();
	                try {
	                        url = new URL(codeBase, filename);
	                } catch (java.net.MalformedURLException e) {
	       		        System.out.println("Couldn't create image: badly specified URL");
	        	        return null;
		        }
	          }
	            else{
		            url=getClass().getResource(filename);
		    }
	       return url;
	}
	
	// pre aplikaciu tu mame main() :-))
	public static void main (String args[]) {
		JFrame f=new JFrame("Java");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Graph3D app = new Graph3D();
	        isApplet=false;
		f.getContentPane().add(app);
		app.init();
        	f.setSize(500,380);
	        f.show();
	}
}