/*Rotation Applet von Thomas Elste (www.elste.org)*/

import java.awt.*;
import java.applet.*;
import java.net.*;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.awt.event.*;
import java.lang.*;
import java.io.*;
import java.lang.String;


public class Rot extends Applet implements MouseMotionListener,MouseListener
{

//------------Bildobjekte-----------------
 private Image tNadel;
	private Image tNadelRot;
	private Image offscreen;

	//-----------Sonstige---------------------
	private Graphics bufferGraphics;
	private MediaTracker mt;
	private URL base;
	int image_h,image_w,i_x,i_y;

	//----------Lookuptabellen für die Rotation------------
	private double sin_lookup[];
	private double cos_lookup[];
	private int currentAngle;

	//------------Konstanten------------------
	final int apWidth=800;
	final int apHeight=600;

/****************************************************************************************************
init Methode
alle Initialisierungsfunktionen des Applets
*****************************************************************************************************/

	public void init()
	{
		resize(apWidth,apHeight);
		currentAngle=0;

		//-----------Lookup Tabellen ausrechnen
		sin_lookup=new double[360];
		for (int i=0;i<360;i++) sin_lookup[i]=Math.sin(Math.toRadians(i));
		cos_lookup=new double[360];
		for (int i=0;i<360;i++) cos_lookup[i]=Math.cos(Math.toRadians(i));


		//-----------neuer Medientracker
		mt = new MediaTracker(this);

		//-----------Appletbasisadresse ermitteln
		try
		{
			base = getDocumentBase();
		}
	        catch (Exception e) {}


		//-----------Bildobjekte fürs Doublebuffering initialisieren
		offscreen = createImage(apWidth,apHeight);
		bufferGraphics = offscreen.getGraphics();


       		addMouseMotionListener(this);
       		addMouseListener(this);

       		String bild=new String(" ");

		try
		{
			bild=getParameter("Bild");
		}
		catch (NumberFormatException e)
		{
		}

		//-----------Bilder und Grafiken laden

       		tNadel=getImage(base,bild);
       		tNadelRot=tNadel;

		
		//-----------Laden überwachen
		mt.addImage(tNadel,1);

		try
		{
			mt.waitForAll();
		}
		catch (InterruptedException e) {}

                image_h=tNadel.getWidth(this)/2;
		image_w=tNadel.getHeight(this)/2;
                //System.out.println(image_h+" "+image_w);
                tNadelRot=irotate(tNadel,image_w,image_h,currentAngle);
		repaint();
	}

	public void start()
	{
	}

	public void stop()
	{

	}

	public void destroy()
	{
	}

/****************************************************************************************************
paint Methode
enthält alle Zeichenfunktionen des Applets
*****************************************************************************************************/

	public void paint(Graphics g)
	{
		int l,tw,th;
		//--------------Puffer leeren--------------------
		bufferGraphics.clearRect(0,0,apWidth,apHeight);

		bufferGraphics.drawImage(tNadelRot,i_x,i_y,this);
		g.drawImage(offscreen,0,0,this);
	}

	public void update(Graphics g)
	{
        	paint(g);
	}

/****************************************************************************************************
mouseMoved Methode
Mausbewegung, hier: verändert Cursor, wenn im aktiven Bereich (z.B. Lampen)
*****************************************************************************************************/

	public void mouseMoved(MouseEvent me)
	{
		i_x=me.getX();
		i_y=me.getY();
		repaint();
	}

	public void mouseDragged(MouseEvent me)
	{
		currentAngle++;
		if(currentAngle>359) currentAngle=0;
		tNadelRot=irotate(tNadel,image_w,image_h,currentAngle);
		repaint();
	}


	public void mouseEntered (MouseEvent me)
	{
	}

	public void mousePressed (MouseEvent me)
	{
	}

	public void mouseClicked (MouseEvent me)
	{
	}

	public void mouseReleased (MouseEvent me)
	{
	}

	public void mouseExited (MouseEvent me)
	{
	}


/****************************************************************************************************
irotate Methode
dreht ein Image Objekt um den Winkel angle und den Punkt i_wi_mid, i_he_mid
*****************************************************************************************************/

	public Image irotate(Image isource, double i_wi_mid, double i_he_mid, int angle)
	{
		int i_wi=isource.getWidth(this);
		int i_he=isource.getHeight(this);
	        int area = i_wi * i_he;
		int source[]  = new int[area];
        	try
        	{
			PixelGrabber pg = new PixelGrabber(isource, 0, 0, i_wi, i_he, source, 0, i_wi);
			pg.grabPixels();
		}
 		catch(InterruptedException e) { }
		int target_2d[][]=new int[i_he+1][i_wi+1];
		int source_2d[][]=new int[i_he+1][i_wi+1];
		int i_alt=0,j_alt=0;
		dim1todim2(source,source_2d,i_wi,i_he);
		for(int i=0;i<i_he;i++)
		{
			for(int j=0;j<i_wi;j++)
			{
				i_alt=(int)(((i-i_he_mid)*cos_lookup[angle]-(j-i_wi_mid)*sin_lookup[angle])+i_he_mid);
				j_alt=(int)(((i-i_he_mid)*sin_lookup[angle]+(j-i_wi_mid)*cos_lookup[angle])+i_wi_mid);
				if(i_alt<0) i_alt=0;
				if(j_alt<0) j_alt=0;
				if(i_alt>i_he-1) i_alt=i_he-1;
				if(j_alt>i_wi-1) j_alt=i_wi-1;
				target_2d[i][j]=source_2d[i_alt][j_alt];
			}
		}
		dim2todim1(target_2d,source,i_wi,i_he);
		return(createImage(new MemoryImageSource(i_wi, i_he, source, 0, i_wi)));
	}

/****************************************************************************************************
dim1todim2 Methode
wandelt ein 1 dimensionales Array in eine 2 dimensionale Matrix um (row major)
*****************************************************************************************************/

	public void dim1todim2(int dim1[],int dim2[][],int w_x,int w_y)
	{
		for(int i=0;i<w_y;i++)
		{
			for(int j=0;j<w_x;j++)
			{
				dim2[i][j]=dim1[i*w_x+j];
			}
		}
	}

/****************************************************************************************************
dim2todim1 Methode
wandelt eine 2 dimensionale Matrix in ein 1 dimensionales Array um (row major)
*****************************************************************************************************/

	public void dim2todim1(int dim2[][],int dim1[],int w_x,int w_y)
	{
		for(int i=0;i<w_y;i++)
		{
			for(int j=0;j<w_x;j++)
			{
				dim1[i*w_x+j]=dim2[i][j];
			}
		}
	}
}