/*
Java Snowflakes.  A CAD tool for building paper snowflakes.
Copyright (C) 2004 Neil Fraser
http://neil.fraser.name/

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License (www.gnu.org) for more details.
*/

import java.awt.*;
import java.applet.*;

public class snowflake extends Applet {
	int lastX = -1;
	int lastY = -1;

	public void init() {
		setLayout(null);
		setSize(400,400);
		setBackground(Color.white);
		setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
		buttonClear = new java.awt.Button();
		buttonClear.setLabel("Clear");
		buttonClear.setBounds(327,10,63,21);
		buttonClear.setCursor(new Cursor(Cursor.HAND_CURSOR));
		add(buttonClear);
		labelPoints = new java.awt.Label("Points:");
		labelPoints.setBounds(10,11,51,18);
		labelPoints.setCursor(new Cursor(Cursor.HAND_CURSOR));
		add(labelPoints);
		choicePoints = new java.awt.Choice();
		choicePoints.addItem("2");
		choicePoints.addItem("3");
		choicePoints.addItem("4");
		choicePoints.addItem("5");
		choicePoints.addItem("6");
		choicePoints.addItem("7");
		choicePoints.addItem("8");
		choicePoints.addItem("9");
		choicePoints.addItem("10");
		choicePoints.addItem("11");
		choicePoints.addItem("12");
		try {
			choicePoints.select(4);
		}
		catch (IllegalArgumentException e) { }
		choicePoints.setCursor(new Cursor(Cursor.HAND_CURSOR));
		add(choicePoints);
		choicePoints.setBounds(61,11,64,20);
	
		SymAction lSymAction = new SymAction();
		buttonClear.addActionListener(lSymAction);
		SymItem lSymItem = new SymItem();
		choicePoints.addItemListener(lSymItem);
	}
	
	java.awt.Button buttonClear;
	java.awt.Label labelPoints;
	java.awt.Choice choicePoints;

	int midX = 1;
	int midY = 1;
	int points = 6;

	public void paint(Graphics g) {
		midX = size().width/2;
		midY = size().height/2;
		int radius = Math.min(midX, midY) - 10;
		g.setColor(new Color(127,127,127));
		g.drawOval(midX-radius,midY-radius, radius*2, radius*2);
		int z;
		double angle;
		for (z=0; z < points; z++) {
			angle = z*2*3.14159/points;
			g.drawLine(midX, midY, (int)(Math.sin(angle)*radius)+midX, (int)(Math.cos(angle)*radius)+midY);
		}
		g.setColor(new Color(191,191,191));
		for (z=0; z < points; z++) {
			angle = (z+0.5)*2*Math.PI/points;
			g.drawLine(midX, midY, (int)(Math.sin(angle)*radius)+midX, (int)(Math.cos(angle)*radius)+midY);
		}
	}

	public boolean mouseDown(Event evt, int x, int y) {
		lastX = x;
		lastY = y;
		return true;
	}

	public boolean mouseUp(Event evt, int x, int y) {
		lastX = -1;
		lastY = -1;
		return true;
	}

	public boolean mouseDrag(Event evt, int x, int y) {
		if (lastX >= 0 && lastY >= 0) {
			int radius1 = (int)Math.sqrt((lastX-midX)*(lastX-midX) + (lastY-midY)*(lastY-midY));
			int radius2 = (int)Math.sqrt((x-midX)*(x-midX) + (y-midY)*(y-midY));
			double angle1 = Math.atan2(lastY-midY, lastX-midX);
			double angle2 = Math.atan2(y-midY, x-midX);
			int mirror1X, mirror1Y, mirror2X, mirror2Y;

			Graphics g = getGraphics();
			int z;
			double angle;
			for (z=0; z < points; z++) {
				angle = z*2*Math.PI/points;
				mirror1X = (int)(Math.cos(angle1+angle)*radius1);
				mirror1Y = (int)(Math.sin(angle1+angle)*radius1);
				mirror2X = (int)(Math.cos(angle2+angle)*radius2);
				mirror2Y = (int)(Math.sin(angle2+angle)*radius2);
				g.drawLine(midX+mirror1X, midY+mirror1Y, midX+mirror2X, midY+mirror2Y);
			}
			for (z=0; z < points; z++) {
				// Disclaimer, I've lost track of what's happening here, but this works.
				if (points/2.0 == Math.floor(points/2))
					angle = z*2*Math.PI/points;
				else
					angle = (0.5+z)*2*Math.PI/points;
				mirror1X = (int)(Math.cos(-angle1+angle)*radius1);
				mirror1Y = (int)(Math.sin(-angle1+angle)*radius1);
				mirror2X = (int)(Math.cos(-angle2+angle)*radius2);
				mirror2Y = (int)(Math.sin(-angle2+angle)*radius2);
				g.drawLine(midX+mirror1X, midY+mirror1Y, midX+mirror2X, midY+mirror2Y);
			}
			lastX = x;
			lastY = y;
		}
		return true;
	}

	class SymAction implements java.awt.event.ActionListener
	{
		public void actionPerformed(java.awt.event.ActionEvent event)
		{
			if (event.getSource() == buttonClear)
				repaint();
		}
	}

	class SymItem implements java.awt.event.ItemListener
	{
		public void itemStateChanged(java.awt.event.ItemEvent event)
		{
			if (event.getSource() == choicePoints) {
				points = Integer.parseInt(choicePoints.getSelectedItem());
				repaint();
			}
		}
	}
}

