/**
 * Program to generate the diagram for fabricating the elliptical
 * porthole frames for Elver
 * Compile with JDK 1.3 or above, then display oval.jpg in a
 * webpage.
 * (c) Will Marsh 2003
 */




import java.util.*;
import java.awt.*;
import java.io.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;




public class El2{
	public static void main(String args[]) throws Exception{

		// set up the bitmap image and the graphics object
		BufferedImage bi = new BufferedImage(800,1000,BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = bi.createGraphics();
		g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		g2d.setColor(Color.white);
		g2d.fillRect(0,0,800,1000);
		g2d.setColor(Color.blue);

		// variables to calculate points of the diagram
		double oldX,oldY,x=0.0,y=0.0;
		double oldXp,oldYp,xp=0.0,yp=0.0;
		boolean first = true;

		// calculate an ellipse using the formula x^2+2*y^2=100
		for(double t = 0.0;t<2*Math.PI;t+=0.03){ // iterate several hundred points
			oldX = x;
			oldY = y;
			x = ex(t);
			y = ey(t);
			oldXp = xp;
			oldYp = yp;
			double exv = exp(t);
			double eyv = eyp(t);
			double s = Math.sqrt(exv*exv+eyv*eyv);
			xp = x+50.0*eyp(t)/s;
			yp = y-50.0*exp(t)/s;
			if(first) first = false;
			else{
				g2d.drawLine((int)oldX,(int)oldY,(int)x,(int)y);
				g2d.drawLine((int)oldXp,(int)oldYp,(int)xp,(int)yp);	
			}

		}


		// 8 segmented
		g2d.setColor(Color.red);
		double oldix = 0.0,ix = 0.0;
		double oldiy = 0.0,iy = 0.0;
		double oldixp2 = 0.0,ixp = 0.0,ixp2 = 0.0;
		double oldiyp2 = 0.0,iyp = 0.0,iyp2 = 0.0;
		first = true;
		for(double t = 0.0+Math.PI/16.0;t<2*Math.PI+Math.PI/16.0+0.1;t+=Math.PI/4.0){

			oldix = ix;
			oldiy = iy;

			ix = ex(t);
			iy = ey(t);

			//g2d.drawLine(300,550,(int)ix,(int)iy);
			double s = Math.sqrt(exp(t)*exp(t)+eyp(t)*eyp(t));
			ixp = ix+50.0*eyp(t)/s;
			iyp = iy-50.0*exp(t)/s;	
			g2d.drawLine((int)ix,(int)iy,(int)ixp,(int)iyp);

			oldixp2 = ixp2;
			oldiyp2 = iyp2;
			
			ixp2 = ix+110.0*eyp(t)/s;
			iyp2 = iy-110.0*exp(t)/s;

			if(first){
				first = false;
			}
			else{


				g2d.drawLine((int)ix,(int)iy,(int)ixp2,(int)iyp2);

				g2d.drawLine((int)oldixp2,(int)oldiyp2,(int)ixp2,(int)iyp2);
				// get the angle at oldixp2,oldiyp2	
				double oldangle = angle(ixp2-oldixp2,iyp2-oldiyp2,oldix-oldixp2,oldiy-oldiyp2);
				
				
	
				g2d.drawString(""+oldangle,(int)oldixp2,(int)oldiyp2);

				// angle at ixp2,iyp2
				double angle = angle(oldixp2-ixp2,oldiyp2-iyp2,ix-ixp2,iy-iyp2);
				g2d.drawString(""+angle,(int)ixp2,(int)iyp2+20);
			}
		}
	


		g2d.drawLine(0,(int)CY,800,(int)CY);

		// write out the bitmap image as a jpeg file
		FileOutputStream fos = new FileOutputStream("oval.jpg");
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
		JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
		param.setQuality((float)0.5,true);
		encoder.setJPEGEncodeParam(param);
		encoder.encode(bi);
		bos.close();
		fos.close();
	}

	// angle between two vectors ax,ay and bx,by
	private static double angle(double ax,double ay,double bx,double by){

		double costheta = (ax*bx+ay*by)/Math.sqrt((ax*ax+ay*ay)*(bx*bx+by*by));
		return Math.acos(costheta)*180.0/Math.PI;
	}


	// the center coordinates of the ellipse positioned within the bitmap image
	private static final double CX = 360.0;
	private static final double CY = 600.0;


	// draw ellipse
	private static double ex(double t){
		return CX+240.0*Math.cos(t);
	}

	private static double ey(double t){
		return CY+240.0*2.0*Math.sin(t);
	}

	// derivatives used for drawing outer ellipse.  This technically is not
	// an ellipse.
	private static double exp(double t){
		return -240.0*Math.sin(t);
	}

	private static double eyp(double t){
		return 240.0*2.0*Math.cos(t);
	}



}
