//RectWaveGuideCanvas.java

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

public class RectWaveGuideCanvas extends Canvas implements MouseListener{
    //private static final Color bgcolor = new Color(236,236,221);
    private static final Color bgcolor = Color.white;
    private static final Color medium1Color = Color.yellow;
    private static final Color medium2Color = Color.cyan;
    private static final int LeftMargin=10, RightMargin=10, TopMargin=10, BottomMargin=10;
    private static final Font labfont = new Font("SanSerif",Font.PLAIN,10);
    private static final Font textfont = new Font("SanSerif",Font.PLAIN,10);
    private static final Font symbolfont = new Font("Serif",Font.PLAIN,12);
    private static final Font symbolfont2 = new Font("Serif",Font.PLAIN,14);
    
    private double a_to_b_ratio, frequency, a, b, epsilon_r, mu_r, phase_velocity, phase_velocity0;
    //private static final double epsilon0 = 8.8541878176E-12; //Units: F/m
    // Approximate epsilon for phase velocity 3 x 10^8 m/s
    private static final double epsilon0 = 8.841941286E-12; 
    private static final double mu0 = 1.25663706144E-6; //Units H/m
    
    private Image im;
    private Graphics buf;
    private String stmp;
    private double temp;
    private boolean IsFocusOn;
    
    public RectWaveGuideCanvas(){
	super();
	IsFocusOn = false;
	setBackground(bgcolor);
	//Listeners
	this.addMouseListener(this);
	a_to_b_ratio = 2.22;
	frequency = 10.0E9;
	mu_r = 1.0;
	epsilon_r = 1.0;
	a = 0.02;
	b =a/a_to_b_ratio;
    }

    public void drawCanvas(Graphics g){
	g.clearRect(0,0,getSize().width,getSize().height);
	g.setColor(Color.black);
	
 	if(IsFocusOn){drawBackLabels(g);}
	drawAxis(g);
	drawGuide(g);
    }
    
    private void drawAxis(Graphics g){
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        double theta = Math.PI/6.0;
	int ArrowPos1, ArrowPos2;
	int Lsize = 30;
        
	g.setColor(Color.gray);
	//Vertical axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,LeftMargin,getSize().height-BottomMargin-Lsize);
	MaestroG.drawArrow(LeftMargin,getSize().height-BottomMargin-Lsize,5,g);
	//Horizontal axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,LeftMargin+Lsize,getSize().height-BottomMargin);
	//Draw up arrow
	MaestroG.drawArrow(LeftMargin+Lsize,getSize().height-BottomMargin,7,g);
	
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	//Third axis
		int tipz = -10;
		int verticz = getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta));
		int horizz = LeftMargin+(int)(Lsize*Math.cos(theta));
		g.drawLine(LeftMargin,getSize().height-BottomMargin,horizz - tipz,verticz + tipz);
		   //LeftMargin+(int)(Lsize*Math.cos(theta)),getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta)));
		   
		//draw oblique arrow head
		Polygon pz = new Polygon();
		pz.addPoint(horizz - tipz,verticz + tipz);
		pz.addPoint(horizz - (tipz + 4),verticz +(tipz + 6));
		pz.addPoint(horizz - (tipz + 7),verticz + (tipz + 2));
		g.drawPolygon(pz);
		g.fillPolygon(pz);
	
	g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	//Draw labels for axes
	g.setFont(new Font("SanSerif",Font.PLAIN,12));
	FontMetrics fm = g.getFontMetrics();
	g.drawString("x",LeftMargin-fm.stringWidth("x")/2,getSize().height-BottomMargin-Lsize-10);
	g.drawString("y",LeftMargin+Lsize+10+fm.stringWidth("y"),
		getSize().height-BottomMargin+fm.getHeight()/3);
	g.drawString("z",LeftMargin+(int)(Lsize*Math.cos(theta))+15,getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta))-7);

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);

    }
    
    private void drawGuide(Graphics g){
	Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	int x1, y1, x2, y2;
	Color MetalColor = Color.lightGray;
	Color MetalColor2 = new Color(235,235,235);
	Color MetalColor3 = new Color(225,225,225);
	Color MetalColor4 = new Color(185,185,185);
	Color MetalColor5 = new Color(200,200,200);
	Color MetalColor6 = new Color(150,150,150);
	double theta = Math.PI/6.0;
	int GuideHeight = getSize().height/2;
	int GuideWidth =  (int)(GuideHeight/a_to_b_ratio);
	int GuideThickness = 4;
	int GuideDepth = 70;
	int GuideXPos = 17*getSize().width/60;
	int GuideYPos = getSize().height - 3 * BottomMargin - GuideHeight;
	int xPoints[] = new int[4];
	int yPoints[] = new int[4];
	int xPoints2[] = new int[4];
	int yPoints2[] = new int[4];
	//External rectangle
	g.setColor(MetalColor2);
	g.fillRect(GuideXPos,GuideYPos,GuideWidth,GuideHeight);
	g.setColor(Color.black);
	g.drawRect(GuideXPos,GuideYPos,GuideWidth,GuideHeight);
	//Internal rectangle
	g.setColor(MetalColor6);
	//g.setColor(MetalColor.darker());
	g.fillRect(GuideXPos+GuideThickness, GuideYPos+GuideThickness,GuideWidth-2*GuideThickness,GuideHeight-2*GuideThickness);
	
	xPoints2[0] = GuideXPos+GuideThickness;
	xPoints2[1] = GuideXPos + GuideWidth-GuideThickness;
	xPoints2[2] = GuideXPos + GuideWidth-GuideThickness;
	
	yPoints2[0] = GuideYPos - GuideThickness + GuideHeight;
	yPoints2[1] = GuideYPos - GuideThickness + GuideHeight;
	yPoints2[2] = GuideYPos-GuideThickness+GuideHeight-(int)((GuideWidth-2*GuideThickness)*Math.tan(theta));
	
	g.setColor(MetalColor5);
	g.fillPolygon(xPoints2,yPoints2,3);

	g.setColor(Color.black);
	g.drawRect(GuideXPos+GuideThickness, GuideYPos+GuideThickness,GuideWidth-2*GuideThickness,GuideHeight-2*GuideThickness);
	
	//Polygons
	//Top side external wall
	
	xPoints[0] = GuideXPos;
	xPoints[1] = GuideXPos + (int)(GuideDepth*Math.cos(theta));
	xPoints[2] = GuideXPos + GuideWidth + (int)(GuideDepth*Math.cos(theta));
	xPoints[3] = GuideXPos + GuideWidth;
	
	yPoints[0] = GuideYPos;
	yPoints[1] = GuideYPos - (int)(GuideDepth*Math.sin(theta));
	yPoints[2] = yPoints[1];
	yPoints[3] = yPoints[0];
	
	g.setColor(MetalColor3);
	g.fillPolygon(xPoints,yPoints,4);
	
	//Right side external wall
	xPoints[0] = GuideXPos + GuideWidth+1;
	xPoints[1] = GuideXPos + +GuideWidth + (int)(GuideDepth*Math.cos(theta));
	xPoints[2] = xPoints[1];
	xPoints[3] = xPoints[0];
	
	yPoints[0] = GuideYPos;
	yPoints[1] = GuideYPos - (int)(GuideDepth*Math.sin(theta));
	yPoints[2] = yPoints[1] + GuideHeight;
	yPoints[3] = yPoints[0] + GuideHeight;
	
	g.setColor(MetalColor4);
	g.fillPolygon(xPoints,yPoints,4);
	
	//lines
	g.setColor(Color.gray);
	//Top Left
	g.drawLine(GuideXPos,GuideYPos,GuideXPos+(int)(GuideDepth*Math.cos(theta)),GuideYPos-(int)(GuideDepth*Math.sin(theta)));
	//Top Right
	g.drawLine(GuideXPos+GuideWidth,GuideYPos,GuideXPos+GuideWidth+(int)(GuideDepth*Math.cos(theta)),GuideYPos-(int)(GuideDepth*Math.sin(theta)));
	//Bottom Right
	g.drawLine(GuideXPos+GuideWidth,GuideYPos+GuideHeight,GuideXPos+GuideWidth+(int)(GuideDepth*Math.cos(theta)),GuideYPos+GuideHeight-(int)(GuideDepth*Math.sin(theta)));
	//Bottom Left, and Internal
	g.drawLine(GuideXPos+GuideThickness,GuideYPos+GuideHeight-GuideThickness,
	   GuideXPos+GuideThickness+(int)(GuideWidth-2*GuideThickness),
	   GuideYPos-GuideThickness+GuideHeight-(int)((GuideWidth-2*GuideThickness)*Math.tan(theta)));
	g.setColor(Color.red);
	//draw arrows and labels around the waveguide
	//vertical line
	g.drawLine(GuideXPos-LeftMargin,GuideYPos+10,GuideXPos-LeftMargin,GuideYPos+GuideHeight-10);
	//up arrow
	MaestroG.drawArrow(GuideXPos-LeftMargin,GuideYPos+10+GuideThickness,5,g);
	//draw down arrow
	MaestroG.drawArrow(GuideXPos-LeftMargin,GuideYPos+GuideHeight-10-GuideThickness,6,g);
	g.drawString("a",GuideXPos-2*LeftMargin,GuideYPos+GuideHeight/2+4);
	
	g.drawLine(GuideXPos-15,GuideYPos+GuideThickness,GuideXPos-5,GuideYPos+GuideThickness);
	g.drawLine(GuideXPos-15,GuideYPos+GuideHeight-GuideThickness,GuideXPos-5,GuideYPos+GuideHeight-GuideThickness);
	g.drawLine(GuideXPos+GuideThickness,GuideYPos+GuideHeight+5,
		   GuideXPos+GuideThickness,GuideYPos+GuideHeight+15);
	g.drawLine(GuideXPos+GuideWidth-GuideThickness,GuideYPos+GuideHeight+5,
		   GuideXPos+GuideWidth-GuideThickness,GuideYPos+GuideHeight+15);
	
	if(a_to_b_ratio < 2.5){
	    //horizontal line
	    g.drawLine(GuideXPos+10,GuideYPos+GuideHeight+BottomMargin,GuideXPos+GuideWidth-10,GuideYPos+GuideHeight+BottomMargin);
	    //draw right arrow
	    MaestroG.drawArrow(GuideXPos+GuideWidth-10-GuideThickness,GuideYPos+GuideHeight+BottomMargin,7,g);
	    //draw left arrow
	    MaestroG.drawArrow(GuideXPos+10+GuideThickness,GuideYPos+GuideHeight+BottomMargin,8,g);	
	    g.drawString("b",GuideXPos+GuideWidth/2-3,GuideYPos+GuideHeight+2*BottomMargin+7);
	}
	else{
	    //horizontal line
	    g.drawLine(GuideXPos-10,GuideYPos+GuideHeight+BottomMargin,GuideXPos+GuideWidth+10,GuideYPos+GuideHeight+BottomMargin);
	    //draw right arrow
	    MaestroG.drawArrow(GuideXPos+GuideWidth+5,GuideYPos+GuideHeight+BottomMargin,8,g);
	    //draw left arrow
	    MaestroG.drawArrow(GuideXPos-5,GuideYPos+GuideHeight+BottomMargin,7,g);	
	    g.drawString("b",GuideXPos+GuideWidth/2-3,GuideYPos+GuideHeight+2*BottomMargin+7); 
	}
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
	g.setColor(Color.black);
	int x =130;
	int y = 58;
	
	g.drawString("    a = "+MaestroA.rounder(a,5)+" [ m ]",x,y);	
	
	 y= 75;
	g.drawString("    b = "+MaestroA.rounder(a/a_to_b_ratio,5)+" [ m ]",x,y);	
	
	
	 x = 180;
	 y = 15;
	double f_normalized;
	
	
	if(frequency < 1.0E3){
		    f_normalized = frequency;
		    //g.drawString("    f =  "+MaestroA.rounder(f_normalized,6)+"   [ Hz ]",x,y);	
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" Hz",g,12,x,y);	
		}
		else if(frequency < 1.0E6 && frequency >= 1.0E3  ){
		    f_normalized = frequency/1.0E3;
		    //g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ kHz ]",x,y);	
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" kHz",g,12,x,y);	
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6 ){
		    f_normalized = frequency/1.0E6;
		    //g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ MHz ]",x,y);	
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" MHz",g,12,x,y);	
		}
		else if(frequency < 1.0E12 && frequency >= 1.0E9 ){
		    f_normalized = frequency/1.0E9;
		    //g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ GHz ]",x,y);	
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" GHz",g,12,x,y);	
		}
		else if(frequency < 1.0E15 && frequency >= 1.0E12 ){
		    f_normalized = frequency/1.0E12;
		    //g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ THz ]",x,y);	
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" THz",g,12,x,y);	
		}
		else{
		    f_normalized = frequency/1.0E12;
		    //g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ THz ]",x,y);
                    MaestroG.subscripterSer5("","f",""," =  "+MaestroA.rounder(f_normalized,3)+" THz",g,12,x,y);	
		}
		
		//MaestroG.subscripter("  ",""," = "+MaestroA.rounder(epsilon_r,4),g,12,5,45);
		//MaestroG.subscripter("  ",""," = "+MaestroA.rounder(mu_r,4),g,12,5,60);
		g.setFont(symbolfont2);
		MaestroG.subscripterSer2("\u03b5","r"," = "+MaestroA.rounder(epsilon_r,4),g,12,5,45);
		MaestroG.subscripterSer2("\u03bc","r"," = "+MaestroA.rounder(mu_r,4),g,12,3,60);
		g.setFont(textfont);
		
		phase_velocity = 1.0/Math.sqrt(epsilon0*mu0*epsilon_r*mu_r);
		phase_velocity0 = 1.0/Math.sqrt(epsilon0*mu0);
		
		if(frequency<1.0E3){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,9)+" [ m";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,9)+" [ m","-1"," ]",g,12,5,15);
		}
		else if(frequency<1.0E6 && frequency>=1.0E3){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,6)+" [ m";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,6)+" [ m","-1"," ]",g,12,5,15);
		}
		else if(frequency<1.0E9 && frequency>=1.0E6){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,5)+" [ m";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,5)+" [ m","-1"," ]",g,12,5,15);
		}
		else if(frequency<30.0E9 && frequency>=1.0E9){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,4)+" [ m";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity,4)+" [ m","-1"," ]",g,12,5,15);
		}
		else if(frequency<3.0E12 && frequency>= 30.0E9){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E3,4)+" [ mm";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E3,4)+" [ mm","-1"," ]",g,12,5,15);
		}
		else if(frequency<3.0E15 && frequency>= 3.0E12){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E6,4)+" [ \u03bcm";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E6,4)+" [ \u03bcm","-1"," ]",g,12,5,15);
		}
		else if(frequency>= 3.0E15){
		    //stmp="| k | = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E9,4)+" [ nm";
		    MaestroG.superscripterk("| k |"," = "+MaestroA.rounder(2.0*Math.PI*frequency/phase_velocity/1.0E9,4)+" [ nm","-1"," ]",g,12,5,15);
		}
		//g.setFont(symbolfont2);
		//g.drawString("k",10,15);
		g.setFont(textfont);
		
		if(frequency == 0.0){
		    MaestroG.subscripter("    ",""," =      [ m ]",g,12,5,30);
		    g.setFont(symbolfont2);
		    g.drawString("  \u221e",35,30);
		    g.setFont(labfont);
		}
		else if(frequency < 1.0E3){
		    temp = phase_velocity/frequency/1.0E6;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,3)+" [ 1,000 km ]",g,12,5,30);
		}
		else if(frequency < 1.0E6 && frequency >= 1.0E3){
		    temp = phase_velocity/frequency/1.0E3;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ km ]",g,12,5,30);
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6){
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(phase_velocity/frequency,3)+" [ m ]",g,12,5,30);
		}
		else if(frequency <30.0E9 && frequency>= 1.0E9){
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(phase_velocity/frequency,6)+" [ m ]",g,12,5,30);
		}
		else if(frequency<3.0E12 && frequency>= 30.0E9){
		    temp = phase_velocity/frequency*1.0E3;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ mm ]",g,12,5,30);
		}
		else if(frequency < 3.0E15 &&frequency>=3.0E12 ){
		    temp = phase_velocity/frequency*1.0E6;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ \u03bc m ]",g,12,5,30);
		}
		else if(frequency>=3.0E15 ){
		    temp = phase_velocity/frequency*1.0E9;
		    MaestroG.subscripter("    ",""," = "+MaestroA.rounder(temp,4)+" [ nm ]",g,12,5,30);
		}
                if(epsilon_r == 1.0 && mu_r == 1.0){
                    MaestroG.subscripterSer("\u03bb","0","",g,12,6,30);
                }
                else{
                    g.setFont(symbolfont2);
                    g.drawString("\u03bb",10,30);
                    g.setFont(textfont);
                }
    }
    
    public synchronized void setRatio(double a_to_b_ratio){
	this.a_to_b_ratio = a_to_b_ratio;
	repaint();
    }
    
    public synchronized void setFrequency(double frequency){
	this.frequency = frequency;
    }
    
    public synchronized void setWidth(double width){
	this.a = width;
    }
    
    public synchronized void setEpsilon(double epsilon){
	this.epsilon_r = epsilon;
	
    }
    
    public synchronized void setMu(double mu){
	this.mu_r = mu;
    }
    
    
    private void drawLabels(Graphics g){
	
    }
    
    private void drawBackLabels(Graphics g){
	
    }
    
    private void drawMedium(Graphics g){
	
    }
    
    private void drawWaves(Graphics g){
	
    }
    
    public void paint(Graphics g){
	    if(im == null){
		im = createImage(getSize().width,getSize().height);
		buf = im.getGraphics();
		drawCanvas(buf);
	    }
	    else{
		drawCanvas(buf);
	    }
	    g.drawImage(im,0,0,null);
    }
    
    
    public void update(Graphics g){
	paint(g);
    }
    
    public void mouseClicked(MouseEvent evt){}
    public void mouseEntered(MouseEvent evt){
	IsFocusOn = true;
	repaint();
    }
    public void mouseExited(MouseEvent evt){
	IsFocusOn = false;
	repaint();
    }
    public void mousePressed(MouseEvent evt){}
    public void mouseReleased(MouseEvent evt){}
}
