//NewGuideCanvas
/* A Java class for
 * Coaxial.java
 * Electromagnetic Transmission Line Applet
 * Applet without Smith Chart - Prepared by Umberto Ravaioli 
 * for 6th edition of Fundamentals of Applied Electromagnetics Book
 * May 2009 - All Rights Reserved
 */   

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;

public class NewGuideCanvas 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 int LeftMargin=20, RightMargin=10, TopMargin=10, BottomMargin=10;
    //private static final Font labfont = new Font("SanSerif",Font.PLAIN,10);
    //private static final Font symbfont= new Font("Serif",Font.PLAIN,12);
    public static Font labfont;
    public static Font symbfont;
    public static Font normalfont;
    private int yBottom;
    private double frequency, a, b, w, epsilon_r, epsilon_r0, mu_r, phase_velocity, phase_velocity0;
    private double a_maximum, w_maximum, b_maximum, sigma2, sigma_metal;
    
    // use approximate epsilon for approximate phase velocity
    //private static final double epsilon0 = 8.8541878176E-12; //Units: F/m
    private static final double epsilon0 = 8.841941286E-12; //Units: F/m
    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;
    
    private NewGuide_State state;
    
    public NewGuideCanvas(NewGuide_State state){
	super();
        this.state = state;
        
	IsFocusOn = false;
	setBackground(bgcolor);
	//Listeners
	this.addMouseListener(this);
	
	a = 10.0; // mm
	a_maximum = 11.0; //mm
	b = 0.005; //mm
	b_maximum = 0.5; //mm
	w = 1.5; //mm
	w_maximum = 11.0; //mm
	epsilon_r = 2.3;
	epsilon_r0 = 1.0;
	mu_r = 1.0;
	frequency = 1.0E9;
	sigma2 = 0.0;
	sigma_metal = 5.8E7 ;
	
        LeftMargin = state.s20;
        RightMargin = state.s10;
        TopMargin = state.s10;
        BottomMargin = state.s10;
    }

    public void drawCanvas(Graphics g){
	g.clearRect(0,0,getSize().width,getSize().height);
	g.setColor(Color.black);
	
 	//if(IsFocusOn){drawBackLabels(g);}
	
	drawGuide(g);
        drawAxis(g);
    }
    
    private void drawAxis(Graphics g){
	double theta = Math.PI/4.0;
	int ArrowPos1, ArrowPos2;
	int Lsize = state.s30;
	
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        g.setColor(Color.black);
        g.drawRect(0,0,getSize().width-1,getSize().height-1);
        
        g.setColor(Color.black);
	//Vertical axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,LeftMargin,getSize().height-BottomMargin-Lsize);
	//MaestroG.drawArrow(LeftMargin,getSize().height-BottomMargin-Lsize,5,g);
        MaestroG.drawArrowScaled(LeftMargin,getSize().height-BottomMargin-Lsize,1,state.sfactor,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);
        MaestroG.drawArrowScaled(LeftMargin+Lsize,getSize().height-BottomMargin,3,state.sfactor,g);
	//Third axis
	g.drawLine(LeftMargin,getSize().height-BottomMargin,
		   LeftMargin+(int)(Lsize*Math.cos(theta)),getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta)));
	g.setColor(Color.black);
        //MaestroG.drawArrow(LeftMargin+(int)(Lsize*Math.cos(theta)),getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta)),9,g);
	MaestroG.drawArrowScaled(LeftMargin+(int)(Lsize*Math.cos(theta)),getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta)),5,state.sfactor,g);
	//Draw labels for axes
	g.setFont(normalfont);
	FontMetrics fm = g.getFontMetrics();
        
	//g.drawString("x",LeftMargin-fm.stringWidth("x")/2,getSize().height-BottomMargin-Lsize-state.s10);
	//g.drawString("y",LeftMargin+Lsize+10+fm.stringWidth("y"), getSize().height-BottomMargin+fm.getHeight()/3);
	//g.drawString("z",LeftMargin+(int)(Lsize*Math.cos(theta))+state.s10,getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta))+state.s2);
        
        MaestroG.subscripter("x","","",g,state.font11,LeftMargin-fm.stringWidth("x")/2,getSize().height-BottomMargin-Lsize-state.s10);
	MaestroG.subscripter("y","","",g,state.font11,LeftMargin+Lsize+10+fm.stringWidth("y"),getSize().height-BottomMargin+fm.getHeight()/3);
	MaestroG.subscripter("z","","",g,state.font11,LeftMargin+(int)(Lsize*Math.cos(theta))+state.s10,getSize().height-BottomMargin-(int)(Lsize*Math.sin(theta))+state.s2);
    }
    
    private void drawGuide(Graphics g){    
	int xLeft, xRight, xCenter, xRef, yCenter;
	int yTop, width, thick, widthmax, amax, thickmax;
	int slabDH;//Thickness of the slab
	int slabDepth; //Depth of the slab
	double theta = Math.PI/4.0;
        
        Graphics2D g2d = (Graphics2D)g;
        
	thickmax = state.s5;
	widthmax = state.s100;
	amax = state.s100;
	if( w_maximum >= a_maximum){
	    amax = (int)(a_maximum/w_maximum*widthmax);
	    thickmax = (int)(b_maximum/a_maximum*amax);
	}
	if(w_maximum < a_maximum){
	    amax = state.s100;
	    widthmax = (int)(w_maximum/a_maximum*amax);
	    thickmax = (int)(b_maximum/a_maximum*amax);
	}
	width = (int)(w/w_maximum*widthmax) + state.s1;
	if(w==0.0){
	    width = 0;
	}
	thick = (int)(b/b_maximum*thickmax) + state.s1;
	if(b==0.0){
	    thick = 0;
	}
	
	Color MetalColor1 = Color.lightGray;
	Color MetalColor2 = new Color(220,220,220);
	Color MetalColor3 = new Color(235,235,235);
	Color graynew = new Color(125,125,125);
            
	xLeft = LeftMargin+state.s20;
	xRight = getSize().width - RightMargin-state.s80;
	xCenter = (xRight+xLeft)/2;
	yCenter = getSize().height/2;
	xRef = xCenter-width/2;
	yBottom = TopMargin+state.s60+(int)(a/a_maximum*amax)+state.s1;
	yTop = TopMargin+state.s60;
	slabDH = state.s5;
	slabDepth = state.s90;
	// Draw waveguide
            Color anularcolor = new Color(215,215,215);
            double raggio_out = (a/a_maximum*amax)/2+state.s7;
            double raggio_in = (a/a_maximum*amax)/2;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            
            int x1 = xCenter+(int)(2*Math.sin(theta)*raggio_out);
            int y1 = yCenter-(int)(3.25*Math.sin(theta)*raggio_out);
            int x2 = xCenter+(int)(3.25*Math.sin(theta)*raggio_out);
            int y2 = yCenter-(int)(2*Math.sin(theta)*raggio_out);
            int far = state.s150;
            
            //cylinder lines inner conductor
            g.setColor(Color.lightGray);
            g.drawLine(xCenter-(int)(Math.sin(theta)*width/2),yCenter-(int)(Math.sin(theta)*width/2),
                       (x1+x2)/2+2*far,(y1+y2)/2-2*far);
            g.setColor(Color.gray);
            g.drawLine(xCenter+(int)(Math.sin(theta)*width/2)-1,yCenter+(int)(Math.sin(theta)*width/2),
                       (x1+x2)/2+2*far,(y1+y2)/2-2*far);
            
            drawStencil(g, getSize().width, getSize().height, (int)raggio_out+state.s1, xCenter, yCenter, bgcolor);
            
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            //cylinder lines outer conductor
            g.setColor(Color.lightGray);
            g.drawLine(xCenter-(int)(Math.sin(theta)*raggio_out),yCenter-(int)(Math.sin(theta)*raggio_out),
                       xCenter+(int)(2*Math.sin(theta)*raggio_out)+far,yCenter-(int)(3.25*Math.sin(theta)*raggio_out)-far);
            g.setColor(Color.gray);
            g.drawLine(xCenter+(int)(Math.sin(theta)*raggio_out),yCenter+(int)(Math.sin(theta)*raggio_out),
                       xCenter+(int)(3.25*Math.sin(theta)*raggio_out)+far,yCenter-(int)(2*Math.sin(theta)*raggio_out)-far);
            
            g.setColor(bgcolor);
            g.fillRect(getSize().width/3,0,2*getSize().width/3,10);
            
            drawAnular(g, (int)(raggio_out), (int)(raggio_in), xCenter, yCenter, anularcolor);
            drawCircleThick(g,(double)(xCenter),(double)(yCenter),raggio_out,1,graynew);
            drawCircleThick(g,(double)(xCenter),(double)(yCenter),raggio_in,1,graynew);
            
	    g.setColor(Color.red);
	   
	    g.drawLine(xCenter,yCenter-(int)(raggio_in)-1,xCenter+(int)(raggio_in)+state.s50,yCenter-(int)(raggio_in)-1);
	    g.drawLine(xCenter,yCenter+(int)(raggio_in),xCenter+(int)(raggio_in)+state.s50,yCenter+(int)(raggio_in));
            
	    if((int)(raggio_in) > state.s10){
		g.drawLine(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in),xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in));
		//MaestroG.drawArrow(xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in)-state.s9,6,g);
		//MaestroG.drawArrow(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in)+state.s8,5,g);
                
                MaestroG.drawArrowScaled(xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in)-state.s8,2,state.sfactor,g);
		MaestroG.drawArrowScaled(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in)+state.s8,1,state.sfactor,g);
	    }
	    else{
		g.drawLine(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in)-state.s12,xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in)+state.s12);
		//MaestroG.drawArrow(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in)-state.s9,6,g);
		//MaestroG.drawArrow(xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in)+state.s8,5,g);
                
                MaestroG.drawArrowScaled(xCenter+(int)(raggio_in)+state.s45,yCenter-(int)(raggio_in)-state.s8,2,state.sfactor,g);
		//MaestroG.drawArrowScaled(xCenter+(int)(raggio_in)+state.s45,yCenter+(int)(raggio_in)+state.s8,1,state.sfactor,g);
	    }
	    
	    Color colorinside = new Color(185,185,185);
            FillCircleSmooth(g,(double)(xCenter),(double)(yCenter),width/2,1,graynew);
	    FillCircleSmooth(g,(double)(xCenter),(double)(yCenter),width/2-1,1,anularcolor);
            //drawCircleThick(g,(double)(xCenter),(double)(yCenter),width/2,1,graynew);
            
            //draw cross on center of structure
            
            g.setColor(Color.white);
            g.drawLine(xCenter-state.s2,yCenter,xCenter+state.s2,yCenter);
            g.drawLine(xCenter,yCenter-state.s2,xCenter,yCenter+state.s2);
            
	    g.setColor(Color.red);
	    g.drawLine(xCenter+(int)(width/2),yCenter,xCenter+(int)(width/2),yCenter-(int)(raggio_in)-state.s30);
	    g.drawLine(xCenter-(int)(width/2),yCenter,xCenter-(int)(width/2),yCenter-(int)(raggio_in)-state.s30);
	    
            if((int)(width/2) > state.s10){
		g.drawLine(xCenter+(int)(width/2),yCenter-(int)(raggio_in)-state.s25,xCenter-(int)(width/2),yCenter-(int)(raggio_in)-state.s25);
		//MaestroG.drawArrow(xCenter+(int)(width/2)-state.s9,yCenter-(int)(raggio_in)-state.s25,7,g);
		//MaestroG.drawArrow(xCenter-(int)(width/2)+state.s8,yCenter-(int)(raggio_in)-state.s25,8,g);
                
                MaestroG.drawArrowScaled(xCenter+(int)(width/2)-state.s8,yCenter-(int)(raggio_in)-state.s25,3,state.sfactor,g);
		MaestroG.drawArrowScaled(xCenter-(int)(width/2)+state.s8,yCenter-(int)(raggio_in)-state.s25,4,state.sfactor,g);
	    }
	    else{
		g.drawLine(xCenter+(int)(width/2)+state.s12,yCenter-(int)(raggio_in)-state.s25,xCenter-(int)(width/2)-state.s13,yCenter-(int)(raggio_in)-state.s25);
		//MaestroG.drawArrow(xCenter+(int)(width/2)+state.s9,yCenter-(int)(raggio_in)-state.s25,8,g);
		//MaestroG.drawArrow(xCenter-(int)(width/2)-state.s10,yCenter-(int)(raggio_in)-state.s25,7,g);
                
                MaestroG.drawArrowScaled(xCenter+(int)(width/2)+state.s7,yCenter-(int)(raggio_in)-state.s25,4,state.sfactor,g);
		MaestroG.drawArrowScaled(xCenter-(int)(width/2)-state.s7,yCenter-(int)(raggio_in)-state.s25,3,state.sfactor,g);
	    }
            
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	    
	    //g.drawString("2a",xCenter-state.s5,yCenter-(int)(raggio_in)-state.s35);
	    //g.drawString("2b",xCenter+(int)(raggio_in)+state.s55,yCenter);
	    
            MaestroG.subscripter("2a","","",g,state.font11,xCenter-state.s5,yCenter-(int)(raggio_in)-state.s35);
	    MaestroG.subscripter("2b","","",g,state.font11,xCenter+(int)(raggio_in)+state.s55,yCenter);
	    
	if(w >= a){
            g.setColor(Color.red);
            int xstart1 = state.s5;
            g.drawString("WARNING!",xstart1, state.s65);
            g.drawString("Reduce ",xstart1, state.s80);
            g.drawString("radius a",xstart1, state.s95);
            g.drawString("or increase",xstart1, state.s110);
            g.drawString("radius b",xstart1, state.s125);
        }
            
        g.setColor(Color.black);
    	int x = state.s100;
	int y = getSize().height-state.s5;
	double f_normalized;
	
	
                if(frequency < 1.0E3){
		    f_normalized = frequency;
		    g.drawString("    f =  "+MaestroA.rounder(f_normalized,6)+"   [ Hz ]",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);	
		}
		else if(frequency < 1.0E9 && frequency >= 1.0E6 ){
		    f_normalized = frequency/1.0E6;
		    g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ MHz ]",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);	
		}
		else if(frequency < 1.0E15 && frequency >= 1.0E12 ){
		    f_normalized = frequency/1.0E12;
		    g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ THz ]",x,y);	
		}
		else{
		    f_normalized = frequency/1.0E12;
		    g.drawString("    f  =  "+MaestroA.rounder(f_normalized,6)+"   [ THz ]",x,y);
		}
		
                MaestroG.subscripter("","r","  = "+MaestroA.rounder(epsilon_r,4),g,state.font12,state.s18,state.s27);
		MaestroG.subscripter("",""," = "+MaestroA.rounder(sigma2,6)+" S/m",g,state.font12,state.s23,state.s13);
		g.drawString("\u03c3",state.s13,state.s13);
		g.drawString("\u03b5",state.s13,state.s27);
		g.setFont(labfont);
		
		int refnew = yTop+state.s30;
		
		g.setColor(Color.blue);
		g.drawLine(state.s15,refnew,xCenter-((int)(a/a_maximum*amax/2)-width/2)/2-width/2-state.s5,refnew);
		g.drawLine(state.s15,state.s35,state.s15,refnew);
		g.drawLine(state.s5,state.s35,state.s45,state.s35);
		g.drawLine(state.s5,state.s5,state.s5,state.s35);
		//MaestroG.drawArrow(xCenter-((int)(a/a_maximum*amax/2)-width/2)/2-width/2-state.s10,refnew,7,g);
		MaestroG.drawArrowScaled(xCenter-((int)(a/a_maximum*amax/2)-width/2)/2-width/2-state.s10,refnew,3,state.sfactor,g);
                
		g.setColor(Color.black);
    }
    
    private void drawCircleThick(Graphics g, double xCenter, double yCenter, double Radius, int thick, Color color){
	
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        Ellipse2D.Double circle = new Ellipse2D.Double(xCenter-Radius,yCenter-Radius,2*Radius,2*Radius);
        g2d.draw(circle);
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}
private void drawStencil(Graphics g, int width, int height, int radius, int xcenter, int ycenter, Color stencilcolor){
	int rule; float alpha;
        rule = AlphaComposite.SRC_OVER;
        alpha = 1.0f;
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(stencilcolor);      
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
        
        Area a1, a2, a3;
        
	Rectangle2D newrect = new Rectangle2D.Double(0.0,0.0,(double)width,(double)height);
        a1 = new Area(newrect);
        Ellipse2D newellipse = new Ellipse2D.Double((double)(xcenter-radius),(double)(ycenter-radius),(double)(radius*2),(double)(radius*2));
        a2 = new Area(newellipse);
        a3 = new Area();
        a3.add(a1);
        a3.subtract(a2);
        g2d.fill(a3);
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}

private void FillCircleSmooth(Graphics g, double xCenter, double yCenter, double Radius, int thick, Color color){
	
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        Ellipse2D.Double circle = new Ellipse2D.Double(xCenter-Radius,yCenter-Radius,2*Radius,2*Radius);
        g2d.fill(circle);
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}

private void drawAnular(Graphics g, int radius1, int radius2, int xcenter, int ycenter, Color stencilcolor){
	int rule; float alpha;
        rule = AlphaComposite.SRC_OVER;
        alpha = 1.0f;
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(stencilcolor);      
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
        
        Area a1, a2, a3;
        
        Ellipse2D newellipse1 = new Ellipse2D.Double((double)(xcenter-radius1),(double)(ycenter-radius1),(double)(radius1*2),(double)(radius1*2));
        a1 = new Area(newellipse1);
        Ellipse2D newellipse2 = new Ellipse2D.Double((double)(xcenter-radius2),(double)(ycenter-radius2),(double)(radius2*2),(double)(radius2*2));
        a2 = new Area(newellipse2);
        a3 = new Area();
        a3.add(a1);
        a3.subtract(a2);
        g2d.fill(a3);        
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
}

    public synchronized void setThick(double b){
	this.b = b;
	repaint();
    }
    
    public synchronized void setThickmax(double b_maximum){
	this.b_maximum = b_maximum;
	repaint();
    }
    
    public synchronized void setStrip(double w){
	this.w = w;
	repaint();
    }
    
    public synchronized void setStripmax(double w_maximum){
	this.w_maximum = w_maximum;
	repaint();
    }
    
    public synchronized void setFrequency(double frequency){
	this.frequency = frequency;
    }
    
    public synchronized void setWidth(double a){
	this.a = a;
    }
    
    public synchronized void setWidthMax(double a_maximum){
	this.a_maximum = a_maximum;
    }
    
    public synchronized void setEpsilon(double epsilon_r){
	this.epsilon_r = epsilon_r;
	
    }
    
    public synchronized void setEpsilon0(double epsilon_r0){
	this.epsilon_r0 = epsilon_r0;
	
    }
    
    public synchronized void setMu(double mu){
	this.mu_r = mu;
    }
    
    public synchronized void setSigma2(double sigma2){
	this.sigma2 = sigma2;
    }
    
    public synchronized void setSigmaMetal(double sigma_metal){
	this.sigma_metal = sigma_metal;
    }
    
    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){}
}
