/*

	File: Ellipse.java
	Author: Jens Trapp <http://www.sm.go.dlr.de/~jens>
	Email:  Jens.Trapp@dlr.de

	Simple Program to calculate points on an ellipse.


*/
import java.awt.*;
import java.applet.*;
import java.lang.*;

//===========================Class: Ellipse=========================
public class Ellipse extends Applet
{
	final String VERSION = "1.2";

	private int parameter_a = 4;		// Parameter
	private int parameter_a_min = 1;
	private int parameter_a_max = 99;

	private int parameter_b = 1;		// Parameter
	private int parameter_b_min = 1;
	private int parameter_b_max = 99;

	private int num_points = 100;		// Number of Points
	private int num_points_min= 10;
	private int num_points_max= 1000;
	
	private int scale = 400;
	private int scale_min = 1;
	private int scale_max = 10000;

	private int point_size = 0;
	private int point_size_min= 0;
	private int point_size_max= 20;

	private int point_distribution= 1;
	private int point_distribution_min= 1;
	private int point_distribution_max= 8;
	private int xoffset= 6;

	private int yoffset= 6;

	Scrollbar
		slider_parameter_a,
		slider_parameter_b,
		slider_num_points,
		slider_point_distribution,
		slider_scale,
		slider_point_size,
		slider_xoffset,
		slider_yoffset;

	String slider_parameter_a_text = "Parameter A: ";
	String slider_parameter_b_text = "Parameter B: ";
	String slider_num_points_text = "# Points ("
		+Integer.toString(num_points_min)
			+"-"
				+Integer.toString(num_points_max)
					+"): ";
	String slider_point_distribution_text = "Point Distribution: ";
	String slider_point_size_text = "Point Size: ";
	String slider_scale_text = "Zoom: ";
	String slider_xoffset_text = "X-Offset: ";
	String slider_yoffset_text = "Y-Offset: ";
	Label
		slider_parameter_a_label,
		slider_parameter_b_label,
		slider_num_points_label,
		slider_point_distribution_label,
		slider_scale_label,
		slider_point_size_label,
		slider_xoffset_label,
		slider_yoffset_label,
		id_label,
		profil_label;

	// Scrollbars for colors
/*
	Scrollbar redSlider,blueSlider,greenSlider;
	Label redLabel, greenLabel, blueLabel;


	String sliderTextRed = "Red (0-255): ";
	String sliderTextGreen = "Green (0-255): ";
	String sliderTextBlue = "Blue (0-255): ";
	Panel colorPanel;
	*/
private int redBits = 0, greenBits = 0, blueBits = 0;

	Font font;
	Panel control_panel;
	Panel points_panel;
	TextArea points_field;

	// Get parameters
public void getParams()
	{
		if(getParameter("parameter_a") !=  null)
		{
			parameter_a = new Integer(new String(getParameter("parameter_a"))).intValue();

			if(parameter_a < parameter_a_min)
				parameter_a = parameter_a_min;
			else if(parameter_a > parameter_a_max)
				parameter_a = parameter_a_max;
		}

		if(getParameter("parameter_b") !=  null)
		{
			parameter_b = new Integer(new String(getParameter("parameter_b"))).intValue();

			if(parameter_b < parameter_b_min)
				parameter_b = parameter_b_min;
			else if(parameter_b > parameter_b_max)
				parameter_b = parameter_b_max;
		}

		if(getParameter("num_points") !=  null)
		{
			num_points = new Integer(new String(getParameter("num_points"))).intValue();

			if(num_points < num_points_min)
				num_points = num_points_min;
			else if(num_points > num_points_max)
				num_points = num_points_max;
		}
		
		if(getParameter("point_distribution") !=  null)
		{
			point_distribution = new Integer(new String(getParameter("point_distribution"))).intValue();

			if(point_distribution < point_distribution_min)
				point_distribution = point_distribution_min;
			else if(point_distribution > point_distribution_max)
				point_distribution = point_distribution_max;
		}


		if(getParameter("scale") !=  null)
		{
			scale = new Integer(new String(getParameter("scale"))).intValue();

			if(scale < scale_min)
				scale = scale_min;
			else if(scale > scale_max)
				scale = scale_max;

			calc_offset();
		}

		if(getParameter("point_size") !=  null)
		{
			point_size = new Integer(new String(getParameter("point_size"))).intValue();

			if(point_size < point_size_min)
				point_size = point_size_min;
			else if(point_size > point_size_max)
				point_size = point_size_max;
		}

		if(getParameter("xoffset") !=  null)
		{
			xoffset = new Integer(new String(getParameter("xoffset"))).intValue();

			if(xoffset < -scale)
				xoffset = -scale;
			else if(xoffset > scale)
				xoffset = scale;
		}

		if(getParameter("yoffset") !=  null)
		{
			yoffset = new Integer(new String(getParameter("yoffset"))).intValue();

			if(yoffset < -scale)
				yoffset = -scale;
			else if(yoffset > scale)
				yoffset = scale;
		}

/*		if(getParameter("redBits") !=  null)
		{
			redBits = new Integer(new String(getParameter("redBits"))).intValue();

			if(redBits < 0)
				redBits = 0;
			else if(redBits > 255)
				redBits = 255;
		}

		if(getParameter("greenBits") !=  null)
		{
			greenBits = new Integer(new String(getParameter("greenBits"))).intValue();

			if(greenBits < 0)
				greenBits = 0;
			else if(greenBits > 255)
				greenBits = 255;
		}

		if(getParameter("blueBits") !=  null)
		{
			blueBits = new Integer(new String(getParameter("blueBits"))).intValue();

			if(blueBits < 0)
				blueBits = 0;
			else if(blueBits > 255)
				blueBits = 255;
		}
		*/
	}

public void reset_values()
	{
		parameter_a = 4;
		parameter_b = 1;
		num_points = 100;
		point_distribution = 1;
		point_size = 0;
		scale = 400;
		xoffset = 0;
		yoffset = 0;

		redBits = 0;
		blueBits = 0;
		greenBits = 0;

	}

private void set_id_label()
	{
		id_label.setText(
Double.toString((double)parameter_b/(double)parameter_a));
	}

public void init()
	{
		getParams();
		reset_values();

		//setBackground(Color.gray);
		font = new Font("Helvetica", Font.BOLD, 12);

		setLayout(new BorderLayout());

		control_panel = new Panel();
		control_panel.setLayout(new GridLayout(1,3));
		add("South", control_panel);

		Container container1_panel=new Panel();
		Container container2_panel=new Panel();
		Container container3_panel=new Panel();
		container1_panel.setLayout(new GridLayout(10,1));
		container2_panel.setLayout(new GridLayout(10,1));
		container3_panel.setLayout(new GridLayout(1,2));

		control_panel.add(container1_panel);
		control_panel.add(container2_panel);

		setForeground(Color.black);

		profil_label= new Label("Thickness:", Label.RIGHT);
		container1_panel.add(profil_label);
		id_label= new Label("", Label.CENTER);
		set_id_label();
		container2_panel.add(id_label);


		slider_parameter_a_label = new Label(slider_parameter_a_text + Integer.toString(parameter_a), Label.RIGHT);
		container1_panel.add(slider_parameter_a_label);
		slider_parameter_a = new Scrollbar(Scrollbar.HORIZONTAL, parameter_a, 1, parameter_a_min, parameter_a_max);
		container2_panel.add(slider_parameter_a);

		slider_parameter_b_label = new Label(slider_parameter_b_text + Integer.toString(parameter_b), Label.RIGHT);
		container1_panel.add(slider_parameter_b_label);
		slider_parameter_b = new Scrollbar(Scrollbar.HORIZONTAL, parameter_b, 1, parameter_b_min, parameter_b_max);
		container2_panel.add(slider_parameter_b);

		slider_num_points_label = new Label(slider_num_points_text + Integer.toString(num_points), Label.RIGHT);
		container1_panel.add(slider_num_points_label);
		slider_num_points = new Scrollbar(Scrollbar.HORIZONTAL, num_points, 1, num_points_min, num_points_max);
		container2_panel.add(slider_num_points);
		
		slider_point_distribution_label = new Label(slider_point_distribution_text + Integer.toString(point_distribution), Label.RIGHT);
		container1_panel.add(slider_point_distribution_label);
		slider_point_distribution = new Scrollbar(Scrollbar.HORIZONTAL, point_distribution, 1, point_distribution_min, point_distribution_max);
		container2_panel.add(slider_point_distribution);

		slider_point_size_label = new Label(slider_point_size_text + Integer.toString(point_size), Label.RIGHT);
		container1_panel.add(slider_point_size_label);
		slider_point_size = new Scrollbar(Scrollbar.HORIZONTAL, point_size, 1, point_size_min, point_size_max);
		container2_panel.add(slider_point_size);

		slider_scale_label = new Label(slider_scale_text + Integer.toString(scale), Label.RIGHT);
		container1_panel.add(slider_scale_label);
		slider_scale = new Scrollbar(Scrollbar.HORIZONTAL, scale, 1, scale_min, scale_max);
		container2_panel.add(slider_scale);

		slider_xoffset_label = new Label(slider_xoffset_text + Integer.toString(xoffset), Label.RIGHT);
		container1_panel.add(slider_xoffset_label);
		slider_xoffset = new Scrollbar(Scrollbar.HORIZONTAL, xoffset, 1, -scale, scale);
		container2_panel.add(slider_xoffset);

		slider_yoffset_label = new Label(slider_yoffset_text + Integer.toString(yoffset), Label.RIGHT);
		container1_panel.add(slider_yoffset_label);
		slider_yoffset = new Scrollbar(Scrollbar.HORIZONTAL, yoffset, 1, -scale/(2*parameter_b), scale/(2*parameter_b));
		container2_panel.add(slider_yoffset);
/*
		redLabel = new Label(sliderTextRed + Integer.toString(redBits), Label.RIGHT);
		container1_panel.add(redLabel);
		redSlider = new Scrollbar(Scrollbar.HORIZONTAL, redBits, 1, 0, 255);
		container2_panel.add(redSlider);

		greenLabel = new Label(sliderTextGreen + Integer.toString(greenBits), Label.RIGHT);
		container1_panel.add(greenLabel);
		greenSlider = new Scrollbar(Scrollbar.HORIZONTAL, greenBits, 1, 0, 255);
		container2_panel.add(greenSlider);

		blueLabel = new Label(sliderTextBlue + Integer.toString(blueBits), Label.RIGHT);
		container1_panel.add(blueLabel);
		blueSlider = new Scrollbar(Scrollbar.HORIZONTAL, blueBits, 1, 0, 255);
		container2_panel.add(blueSlider);
		*/
		container3_panel.add(new Button("Reset"));
		container3_panel.add(new Button("Help"));
		container1_panel.add(container3_panel);
		container2_panel.add(new Button("Show Points"));

		points_field = new TextArea();
		points_field.setEditable(true);
		control_panel.add(points_field);

	}

private void calc_offset()
	{
		if (xoffset>scale)
			xoffset=scale;
		else if (-xoffset>scale)
			xoffset=-scale;
		slider_xoffset.setValues(xoffset, 1, -scale, scale);

		if (yoffset>scale)
			yoffset=scale;
		else if (-yoffset>scale)
			yoffset=-scale;
		slider_yoffset.setValues(yoffset, 1, -scale*parameter_b, scale*parameter_b);
		control_panel.repaint();

	}



public boolean handleEvent(Event e)
	{
		if (e.target instanceof Scrollbar) {
			int value = ((Scrollbar)e.target).getValue();

			if (e.target == slider_parameter_a) {
				slider_parameter_a_label.setText(slider_parameter_a_text + Integer.toString(value));
				parameter_a = value;
				set_id_label();
			} else if (e.target == slider_parameter_b) {
				slider_parameter_b_label.setText(slider_parameter_b_text + Integer.toString(value));
				parameter_b = value;
				set_id_label();
			} else if (e.target == slider_num_points) {
				slider_num_points_label.setText(slider_num_points_text + Integer.toString(value));
				num_points = value;
			} else if (e.target == slider_point_distribution) {
				slider_point_distribution_label.setText(slider_point_distribution_text + Integer.toString(value));
				point_distribution = value;
			} else if (e.target == slider_scale) {
				slider_scale_label.setText(slider_scale_text + Integer.toString(value));
				scale = value;
				calc_offset();
			} else if (e.target == slider_point_size) {
				slider_point_size_label.setText(slider_point_size_text + Integer.toString(value));
				point_size = value;
			} else if (e.target == slider_xoffset) {
				slider_xoffset_label.setText(slider_xoffset_text + Integer.toString(value));
				xoffset = value;
			} else if (e.target == slider_yoffset) {
				slider_yoffset_label.setText(slider_yoffset_text + Integer.toString(value));
				yoffset = value;
			}
/*
			else if (e.target == redSlider) {
				redLabel.setText(sliderTextRed + Integer.toString(value));
				redBits=value;
			} else if (e.target == greenSlider) {
				greenLabel.setText(sliderTextGreen + Integer.toString(value));
				greenBits=value;
			} else if (e.target == blueSlider) {
				blueLabel.setText(sliderTextBlue + Integer.toString(value));
				blueBits=value;
			}

			*/
			repaint();
			//			play(getDocumentBase(), audioScroll);

			return true;
		}

		return super.handleEvent(e);
	}

public boolean action(Event e, Object arg)
	{
		if("Reset".equals(arg)){
			reset_values();
			set_id_label();
			slider_parameter_a_label.setText(slider_parameter_a_text + Integer.toString(parameter_a));
			slider_parameter_b_label.setText(slider_parameter_b_text + Integer.toString(parameter_b));
			slider_num_points_label.setText(slider_num_points_text + Integer.toString(num_points));
			slider_point_distribution_label.setText(slider_point_distribution_text + Integer.toString(point_distribution));

			slider_scale_label.setText(slider_scale_text + Integer.toString(scale));
			slider_point_size_label.setText(slider_point_size_text + Integer.toString(point_size));
			slider_xoffset_label.setText(slider_xoffset_text + Integer.toString(xoffset));
			slider_yoffset_label.setText(slider_yoffset_text + Integer.toString(yoffset));
			slider_parameter_a.setValue(parameter_a);
			slider_parameter_b.setValue(parameter_b);
			slider_num_points.setValue(num_points);
			slider_point_distribution.setValue(point_distribution);
			slider_scale.setValue(scale);
			slider_point_size.setValue(point_size);
			slider_xoffset.setValue(xoffset);
			slider_yoffset.setValue(yoffset);
/*
			redLabel.setText(sliderTextRed + Integer.toString(redBits));
			greenLabel.setText(sliderTextGreen + Integer.toString(greenBits));
			blueLabel.setText(sliderTextBlue + Integer.toString(blueBits));
			redSlider.setValue(redBits);
			greenSlider.setValue(greenBits);
			blueSlider.setValue(blueBits);
			play(getCodeBase(), audioButton);

			*/
			points_field.setText("");
			repaint();

			return true;
		}
		else if("Show Points".equals(arg)){
			double	x[],y[];
			int i;

			x=new double[num_points*2];
			y=new double[num_points*2];

			points_field.setText("");

			if (calc_ellipse(x, y,num_points)==0)
			{
				points_field.appendText("Not a Valid Airfoil!!\n");
			}
			else
			{
				points_field.appendText("#Thickness:" + id_label.getText()+"\n");

				//lower side
				for(i=1; i<num_points; i++){
					points_field.appendText(
						Double.toString(x[i])
						+" "
						+Double.toString(y[i])+"\n");
				}

				//uper side
				for(i=1; i<num_points; i++){
					points_field.appendText(
						Double.toString(x[num_points+i])
						+" "
						+Double.toString(y[num_points+i])+"\n");
				}
			}

			repaint();
		}
		else if("Help".equals(arg)){
			points_field.setText(
				"(c) DLR 1996\n"
				+"Jens.Trapp@dlr.de\n"
				+"Simple Ellipse\n"
				+"All points x-values lie \n"
				+"between  0 - 1.\n"
				+"The thickness is calculated\n"
				+"from the ratio b/a.\n"
				+"The ellipse will have\n"
				+"the given point number on\n"
				+"each side.\n"
				);

		}

		return true;
	}

	int  calc_ellipse(double	x[], double y[], int num_pts)
	{
		int i;
		double xs = 0;
		double xe = Math.PI;
		double step=(double) ((xe-xs)/(double)(num_pts-1));
		int pt_dist= (int)Math.pow(2,point_distribution);
		
		for (i=0; i<num_pts; i++)
		{
			double xc_distributed=1;

			int oi=(2*num_pts-i-1);
			double tmp=xs+i*step;
		
			x[i]=(float)(parameter_a*Math.cos(tmp)+parameter_a)/(2*parameter_a);
			for (int jj=0;jj<pt_dist;jj++)
				xc_distributed*=x[i];
			x[i]=xc_distributed;
			
			double xv = Math.acos(2*x[i]-1);		
			y[i]=(float) ((parameter_b*Math.sin(xv))/(2*parameter_a));
			y[oi]=-(float) y[i];
			x[oi]=x[i];
		}

		return 1;
	}

public void paint(Graphics g)
	{
		double	x[],y[];
		int i;
		int center_x = 50;
		int center_y = 150;
		int offset_factor = 1;
		g.setFont(font);
		//g.clipRect(0,0,1000,1000);

		g.setColor(new Color(redBits, greenBits, blueBits));

		x=new double[num_points*2];
		y=new double[num_points*2];

		if (calc_ellipse(x, y,num_points)==0)
		{
			id_label.setText("Not a Valid Airfoil!!");
		}

		//lower side
		for(i=1; i<num_points; i++){
			g.drawLine(
				xoffset*offset_factor+(int)(x[i-1]*scale)+center_x,
				yoffset*offset_factor+(int)(-y[i-1]*scale)+center_y,
				xoffset*offset_factor +(int)(x[i]*scale)+center_x,
				yoffset*offset_factor +(int)(-y[i]*scale)+center_y);
		}

		//uper side
		for(i=1; i<num_points; i++){
			g.drawLine(
				xoffset*offset_factor + (int)(x[num_points+i-1]*scale)+center_x,
				yoffset*offset_factor + (int)(-y[num_points+i-1]*scale)+center_y,
				xoffset*offset_factor +(int)(x[num_points+i]*scale)+center_x,
				yoffset*offset_factor +(int)(-y[num_points+i]*scale)+center_y);
		}

		if (point_size>0)
		{
			//lower side
			for(i=0; i<num_points; i++){
				g.drawOval(
					xoffset*offset_factor +(int)(x[i]*scale-point_size/2)+center_x,
					yoffset*offset_factor +(int)(-y[i]*scale-point_size/2)+center_y,
					point_size, point_size);
			}

			//uper side
			for(i=0; i<num_points; i++){
				g.drawOval(
					xoffset*offset_factor +(int)(x[num_points+i]*scale-point_size/2)+center_x,
					yoffset*offset_factor +(int)(-y[num_points+i]*scale-point_size/2)+center_y,
					point_size, point_size);
			}
		}
	}

}


