//GraphCanvas.java

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class GraphCanvasD extends Canvas {
    protected static final Color bgcolor = new Color(216,216,191);
    protected Image im;
    protected Graphics buf;
    protected int LeftMargin;
    protected int TopSep;
    protected int BottomSep;
    protected int RightMargin;
    protected int VPos=0;
    protected String XLabel, YLabel, TITLE;
    protected String X1, X2, X3;
    protected String Y1, Y2, Y3;
    protected int NumPoints;
    protected double x[];
    protected double y[];
    protected double phi_angle;
    protected double ymin, ymax;
    protected double xmin, xmax;
    protected int xx[];
    protected int yy[];
    protected int flag, xshifto;
    protected int type;
    protected double xRef;
    protected boolean Should_Plot_Zero_Line;
    protected boolean Should_Plot_Ref_Point;
    protected boolean IsYRangeMinSet, IsYRangeMaxSet;
    protected boolean IsXRangeMinSet, IsXRangeMaxSet;
    protected boolean IsPolar, is_theta_plane;
    protected Font font1;
    private boolean IsFocusOn, IsTopoOn;
    NewGuide_State state;
    
    private BufferedImage infinity;
    
    public GraphCanvasD(NewGuide_State state){
	super();
        this.state = state;
	getImages();
        
        font1 = new Font("Serif",Font.PLAIN,state.font12);
    
        LeftMargin = state.s40;
        TopSep = state.s40;
        BottomSep = state.s40;
        RightMargin = state.s40;
    
	setBackground(bgcolor);
	XLabel="x-axis";
	YLabel="y-axis";
	TITLE ="Unknown Title";
	Y1 = " ";
	Y2 = " ";
	Y3 = " ";
	X1 = " ";
	X2 = " ";
	X3 = " ";
	NumPoints = 1001;
	x = new double[NumPoints];
	y = new double[NumPoints];
	xx = new int[NumPoints];
	yy = new int[NumPoints];
	for(int i=0;i<NumPoints;i++){
	    x[i]=i;
	    y[i]=0.0;
	}
	IsYRangeMinSet=false;
	IsYRangeMaxSet=false;
	IsXRangeMinSet=false;
	IsXRangeMaxSet=false;
	IsPolar = false;
	is_theta_plane = false;
	
	IsFocusOn = false;
	IsTopoOn = false;
	
	phi_angle = 45.0;
	type = 1;
	xRef = 0.0;
	xshifto = state.s30;
	Should_Plot_Zero_Line = false;
	Should_Plot_Ref_Point = false;
    }


    private void getImages() {
        // read in the infinity image, because CHEERPJ does not render this
	//  symbol in any font!  (java to javascript converter)
        try {
            //infinity = ImageIO.read(getClass().getResource("infinity.png"));
	    BufferedImage img =
		ImageIO.read(getClass().getResource("infinity.png"));
	    int targetWidth = (int) (state.sfactor * img.getWidth());
	    int targetHeight = (int) (state.sfactor * img.getHeight());
	    infinity =
		new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
	    Graphics2D graphics2D = infinity.createGraphics();
	    graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
					RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	    graphics2D.drawImage(img, 0, 0, targetWidth, targetHeight, 0, 0,
				 img.getWidth(), img.getHeight(), null);
	    graphics2D.dispose();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
     
    public void paint(Graphics g){

        if(im == null){
            im = createImage(getSize().width,getSize().height);
            buf = im.getGraphics();
            if(!IsPolar){
                drawGraph(buf);
            }
            else{
                drawGraph2(buf);
            }
        }
        if(!IsPolar){
            drawGraph(buf);
        }
        else{
                drawGraph2(buf);
        }
        g.drawImage(im,0,0,null);

        if(IsTopoOn && IsPolar){
            g.setFont(new Font("SanSerif",Font.PLAIN,state.font11));
            if(!IsFocusOn){
                g.setColor(Color.blue);
                g.drawString("Click to hide dipoles ",getSize().width/2+state.s30,getSize().height-state.s10);
            }
            else{
                g.setColor(new Color(150,0,0));
                g.drawString("Click to show dipoles",getSize().width/2+state.s30,getSize().height-state.s10);
            }
        }
    }

    public void drawGraph(Graphics g){
	g.clearRect(0,0,getSize().width,getSize().height);
    	drawAxis(g);
	if(Should_Plot_Zero_Line){plotZeroLine(g);}
	//g.draw3DRect(0,0,getSize().width-1,getSize().height-1,false);
	drawTitle(g);
        plotPoints(g);
	if(Should_Plot_Ref_Point){plotRefPoint(g);}
	
    }
    
    public void drawGraph2(Graphics g){
	g.clearRect(0,0,getSize().width,getSize().height);
	        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        int i;
        double theta;
        double geom;
        int rwidth = state.s200+state.s96;
        int rheight = state.s200+state.s96;
        double phi;
        phi = (double)((int)(phi_angle));
        
        g.setColor(Color.lightGray);
        
        g.fill3DRect(0,0,rwidth-1,rheight-1,true);
        
        g.setColor(Color.black);
        if(type == 1){MaestroG.subscripterSymbol("| E","\u03b8"," |",g,state.font14,state.s20,state.s20);}
        if(type == 2){MaestroG.subscripter2("| E","R"," |",g,state.font14,state.s20,state.s20);}
        if(type == 3){MaestroG.subscripter2("| E","x"," |",g,state.font14,state.s20,state.s20);}
        if(type == 4){MaestroG.subscripter2("| E","y"," |",g,state.font14,state.s20,state.s20);}
        if(type == 5){MaestroG.subscripter2("| E","z"," |",g,state.font14,state.s20,state.s20);}
        if(type == 6){MaestroG.subscripterSymbol("| H","\u03c6"," |",g,state.font14,state.s20,state.s20);}
        if(type == 7){MaestroG.subscripter2("| H","x"," |",g,state.font14,state.s20,state.s20);}
        if(type == 8){MaestroG.subscripter2("| H","y"," |",g,state.font14,state.s20,state.s20);}
        
        if(type == 9){MaestroG.subscripter2("| H","z"," |",g,state.font14,state.s20,state.s20);}
        if(type == 10){MaestroG.subscripterSymbol("| E","\u03c6"," |",g,state.font14,state.s20,state.s20);}
        if(type == 11){MaestroG.subscripter2("| H","R"," |",g,state.font14,state.s20,state.s20);}
        if(type == 12){MaestroG.subscripterSymbol("| H","\u03b8"," |",g,state.font14,state.s20,state.s20);}
        
        g.setColor(Color.white);
        //draw concentric circles
        g.drawOval((int)(rwidth*0.4),(int)(rwidth*0.4),(int)(rwidth*0.20),(int)(rwidth*0.20));
        g.drawOval((int)(rwidth*0.3),(int)(rwidth*0.3),(int)(rwidth*0.40),(int)(rwidth*0.40));
        g.drawOval((int)(rwidth*0.2),(int)(rwidth*0.2),(int)(rwidth*0.60),(int)(rwidth*0.60));
        g.drawOval((int)(rwidth*0.1),(int)(rwidth*0.1),(int)(rwidth*0.80),(int)(rwidth*0.80));
        
        //draw radial lines
        g.drawLine((int)(rwidth*0.1),(int)(rwidth*0.5),(int)(rwidth*0.9),(int)(rwidth*0.5));
        g.drawLine((int)(rwidth*0.5),(int)(rwidth*0.1),(int)(rwidth*0.5),(int)(rwidth*0.9));
        g.drawLine( (int)(rwidth*(0.5+0.4*(0.866))), (int)(rwidth*(0.5+0.4*(0.5))), 
                    (int)(rwidth*(0.5-0.4*(0.866))), (int)(rwidth*(0.5-0.4*(0.5))));
        g.drawLine( (int)(rwidth*(0.5-0.4*(0.866))), (int)(rwidth*(0.5+0.4*(0.5))), 
                    (int)(rwidth*(0.5+0.4*(0.866))), (int)(rwidth*(0.5-0.4*(0.5))));
        g.drawLine( (int)(rwidth*(0.5+0.4*(0.5))), (int)(rwidth*(0.5+0.4*(0.866))), 
                    (int)(rwidth*(0.5-0.4*(0.5))), (int)(rwidth*(0.5-0.4*(0.866))));
        g.drawLine( (int)(rwidth*(0.5-0.4*(0.5))), (int)(rwidth*(0.5+0.4*(0.866))), 
                    (int)(rwidth*(0.5+0.4*(0.5))), (int)(rwidth*(0.5-0.4*(0.866))));
        
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
        g.setColor(Color.black);
        //write the angles
        if(is_theta_plane==true){	
            g.setColor(Color.red);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            g.setFont(new Font("Serif",Font.PLAIN,state.font22));
            g.drawString("\u03b8",20,getSize().height-state.s25);

            g.setColor(Color.blue);
            g.setFont(new Font("Serif",Font.PLAIN,state.font13));
            g.drawString("\u03c6 = "+(int)(phi)+"\u00ba",rwidth-state.s50,state.s20);

            g.setColor(Color.black);
            g.setFont(new Font("Sanserif",Font.PLAIN,state.font11));
            g.drawString("0\u00ba",(int)(rwidth*  (0.5-0.42*(0.030)))+state.s2,(int)(rwidth*(0.5+0.42*(-1.00))));
            g.drawString("30\u00ba",(int)(rwidth* (0.5+0.42*(0.500))),(int)(rwidth*(0.5+0.43*(-0.866))));
            g.drawString("-30\u00ba",(int)(rwidth* (0.5-0.44*(0.500))-state.s8),(int)(rwidth*(0.5+0.43*(-0.866))));
            g.drawString("60\u00ba",(int)(rwidth* (0.5+0.42*(0.866))),(int)(rwidth*(0.5+0.44*(-0.47))));
            g.drawString("-60\u00ba",(int)(rwidth* (0.5-0.44*(1.0))),(int)(rwidth*(0.5+0.44*(-0.47))));
            g.drawString("90\u00ba",(int)(rwidth* (0.5+0.42*(1.000))),(int)(rwidth*(0.5+0.42*(0.05))));
            g.drawString("-90\u00ba",(int)(rwidth* (0.5-0.46*(1.055))),(int)(rwidth*(0.5+0.45*(0.05))));
            g.drawString("120\u00ba",(int)(rwidth*(0.5+0.43*(0.866))),(int)(rwidth*(0.5+0.48*(0.50))));
            g.drawString("-120\u00ba",(int)(rwidth*(0.5-0.48*(0.95))),(int)(rwidth*(0.5+0.48*(0.50))));
            g.drawString("150\u00ba",(int)(rwidth*(0.5+0.42*(0.450))),(int)(rwidth*(0.5+0.47*(0.866))));
            g.drawString("-150\u00ba",(int)(rwidth*(0.5-0.47*(0.550))),(int)(rwidth*(0.5+0.47*(0.866))));
            g.drawString("180\u00ba",(int)(rwidth*(0.5-0.42*(0.070))),(int)(rwidth*(0.5+0.43*(1.05))));
        }
        else{   
            g.setColor(Color.red);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            g.setFont(new Font("Serif",Font.PLAIN,state.font22));
            g.drawString("\u03c6",state.s20,getSize().height-state.s25);

            g.setColor(Color.blue);
            g.setFont(new Font("Serif",Font.PLAIN,state.font13));
            g.drawString("\u03b8 = 90\u00ba",rwidth-state.s45,state.s20);

            g.setFont(new Font("Sanserif",Font.PLAIN,state.font11));
            g.setColor(Color.black);
            g.drawString("180\u00ba",(int)(rwidth*  (0.5-0.60*(0.050))),(int)(rwidth*(0.5+0.42*(-1.00))));
            g.drawString("150\u00ba",(int)(rwidth* (0.5+0.42*(0.4500))),(int)(rwidth*(0.5+0.43*(-0.866))));
            g.drawString("210\u00ba",(int)(rwidth* (0.5-0.47*(0.550))),(int)(rwidth*(0.5+0.43*(-0.866))));
            g.drawString("120\u00ba",(int)(rwidth* (0.5+0.42*(0.866))),(int)(rwidth*(0.5+0.44*(-0.47))));
            g.drawString("240\u00ba",(int)(rwidth* (0.5-0.44*(1.0))),(int)(rwidth*(0.5+0.44*(-0.47))));
            g.drawString("90\u00ba",(int)(3+rwidth* (0.5+0.41*(1.000))),(int)(rwidth*(0.5+0.10*(0.1))));
            g.drawString("270\u00ba",(int)(rwidth* (0.5-0.44*(1.10))),(int)(rwidth*(0.5+0.10*(0.1))));
            g.drawString("60\u00ba",(int)(rwidth*(0.5+0.43*(0.866))),(int)(rwidth*(0.5+0.48*(0.50))));
            g.drawString("300\u00ba",5+(int)(rwidth* (0.5-0.44*(1.0))),(int)(rwidth*(0.5+0.48*(0.50))));
            g.drawString("30\u00ba",(int)(rwidth*(0.5+0.42*(0.450))),(int)(rwidth*(0.5+0.47*(0.866))));
            g.drawString("330\u00ba",(int)(rwidth*(0.5-0.47*(0.550))),(int)(rwidth*(0.5+0.47*(0.866))));
            g.drawString("0\u00ba",(int)(rwidth*(0.5-0.2*(0.030))),(int)(rwidth*(0.5+0.43*(1.05))));
        }
        if(is_theta_plane==true){//This is the theta plane
            //draw dipole antenna
            geom = (rwidth*0.16*Math.cos((45-90)*Math.PI/180));
            
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            
            g.setColor(Color.red);
            g.drawLine((int)(rwidth*(0.5)-geom+1),(int)(rwidth*(0.5-0.1)),
                   (int)(rwidth*(0.5)-geom+1),(int)(rwidth*(0.5-0.01)));
            g.drawLine((int)(rwidth*(0.5)-geom+1),(int)(rwidth*(0.5+0.1)),
                   (int)(rwidth*(0.5)-geom+1),(int)(rwidth*(0.5+0.01)));
            g.drawLine((int)(rwidth*(0.5)-geom),(int)(rwidth*(0.5-0.1)),
                   (int)(rwidth*(0.5)-geom),(int)(rwidth*(0.5-0.01)));
            g.drawLine((int)(rwidth*(0.5)-geom),(int)(rwidth*(0.5+0.1)),
                   (int)(rwidth*(0.5)-geom),(int)(rwidth*(0.5+0.01)));
            g.drawLine((int)(rwidth*(0.5)-geom-1),(int)(rwidth*(0.5-0.1)),
                   (int)(rwidth*(0.5)-geom-1),(int)(rwidth*(0.5-0.01)));
            g.drawLine((int)(rwidth*(0.5)-geom-1),(int)(rwidth*(0.5+0.1)),
                   (int)(rwidth*(0.5)-geom-1),(int)(rwidth*(0.5+0.01)));
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        }
        else{//This is phi plane
             // Draw cross-section line 
             g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

            g.setColor(Color.yellow);

            double phi2 = phi - 90.0;
            if(phi == 360.0){phi2 = -90.0;}

            xshifto = (int)(rwidth * 0.16);
            g.drawLine((int)((rwidth/2.0)*(1.0+0.8*Math.cos(phi2*Math.PI/180.0))),
                     (int)((rwidth/2.0)*(1.0-0.8*Math.sin(phi2*Math.PI/180.0))),
                     (int)((rwidth/2.0)*(1.0-0.8*Math.cos(phi2*Math.PI/180.0))),
                     (int)((rwidth/2.0)*(1.0+0.8*Math.sin(phi2*Math.PI/180.0))));

            // Draw Wires - view from top
            if(!IsFocusOn){
                g.setColor(Color.red);
                g.fillOval(
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2-xshifto,
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2,
                (int)(rwidth*(0.025)),
                (int)(rwidth*(0.025)));

                g.setColor(Color.black);
                g.drawOval(
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2-xshifto,
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2,
                (int)(rwidth*(0.025)),
                (int)(rwidth*(0.025)));

                g.setColor(Color.green);
                g.fillOval(
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2+xshifto,
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2,
                (int)(rwidth*(0.025)),
                (int)(rwidth*(0.025)));

                g.setColor(Color.black);
                g.drawOval(
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2+xshifto,
                (int)(rwidth*(0.5)-rwidth*(0.00625))-state.s2,
                (int)(rwidth*(0.025)),
                (int)(rwidth*(0.025)));
            }
            //Draw view-angle arrow
            
            //g.setColor(Color.white);
            g.setColor(Color.black);
            g.drawLine((int)((rwidth/2.0)*(1.0+0.63*Math.cos((phi2-90.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0-0.63*Math.sin((phi2-90.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0+0.815*Math.cos((phi2-90.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0-0.815*Math.sin((phi2-90.0)*Math.PI/180.0))));

            g.setColor(Color.yellow);
            Polygon s = new Polygon();
            s.addPoint((int)((rwidth/2.0)*(1.0+0.63*Math.cos((phi2-90.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0-0.63*Math.sin((phi2-90.0)*Math.PI/180.0))));
            s.addPoint((int)((rwidth/2.0)*(1.0+0.72*Math.cos((phi2-94.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0-0.72*Math.sin((phi2-94.0)*Math.PI/180.0))));
            s.addPoint((int)((rwidth/2.0)*(1.0+0.72*Math.cos((phi2-86.0)*Math.PI/180.0))),
                    (int)((rwidth/2.0)*(1.0-0.72*Math.sin((phi2-86.0)*Math.PI/180.0))));

            g.fillPolygon(s);
            g.setColor(Color.black);
            g.drawPolygon(s);
        }

        //Now draw the radiation diagram
        g.setColor(Color.blue);
        double offset = 0.39;
	if(is_theta_plane==true){
		
        //Now draw radiation patterns
        double theta2 = 0.0;
        for(i=0;i<359;i++){
            theta = (2.0*Math.PI*i/360.0-Math.PI/2.0);
            theta2 = (2.0*Math.PI*(i+1)/360.0-Math.PI/2.0);
            g.setColor(Color.blue);
            g.drawLine(
                (int)(rwidth*(0.5+offset*y[i]/ymax*Math.cos(theta))),
                (int)(rwidth*(0.5+offset*y[i]/ymax*Math.sin(theta))),
                (int)(rwidth*(0.5+offset*y[i+1]/ymax*Math.cos(theta2))),
                (int)(rwidth*(0.5+offset*y[i+1]/ymax*Math.sin(theta2))));
            }
            //Add point at 360 dedgrees
            theta = (2.0*Math.PI*359/360.0-Math.PI/2.0);
            theta2 = (2.0*Math.PI*360/360.0-Math.PI/2.0);
            g.setColor(Color.blue);
            g.drawLine(
                (int)(rwidth*(0.5+offset*y[0]/ymax*Math.cos(theta))),
                (int)(rwidth*(0.5+offset*y[0]/ymax*Math.sin(theta))),
                (int)(rwidth*(0.5+offset*y[1]/ymax*Math.cos(theta2))),
                (int)(rwidth*(0.5+offset*y[1]/ymax*Math.sin(theta2))));
            }
            else{
                double phi4 = 0.0;
		for(i=0;i<360;i++){		
		    double phi3;
		    phi3=(2.0*Math.PI*i/360.0);
		    phi4=(2.0*Math.PI*(i+1)/360.0); 
		    g.setColor(Color.blue);
		    g.drawLine(
                        (int)(rwidth*(0.5+offset*y[i]/ymax*Math.sin(phi3))),
                        (int)(rwidth*(0.5+offset*y[i]/ymax*Math.cos(phi3))),
                        (int)(rwidth*(0.5+offset*y[i+1]/ymax*Math.sin(phi4))),
                        (int)(rwidth*(0.5+offset*y[i+1]/ymax*Math.cos(phi4)))); 
		}
	    }
	    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }

    protected void ignition(){
        int height=getSize().height;
        int width=getSize().width;
        if(!IsYRangeMinSet){ymin = MaestroA.getMin(y);}
        if(!IsYRangeMaxSet){ymax = MaestroA.getMax(y);}
        if(!IsXRangeMaxSet){xmax = x[x.length-1];}
        if(!IsXRangeMinSet){xmin = x[0];}
        if(IsYRangeMinSet || IsYRangeMaxSet){
            MaestroA.confiner(y,ymax,ymin);
        }
        if(IsXRangeMinSet || IsXRangeMaxSet){
            MaestroA.confiner(x,xmax,xmin);
        }
        
        if(ymin==ymax){ymax=2*ymin+state.s1;}
        for(int i=0;i<xx.length;i++){
            xx[i]= (int)MaestroA.mapper(x[i],(double)(width-RightMargin),(double)(LeftMargin),xmax,xmin);
            yy[i]= (int)MaestroA.mapper(y[i],(double)TopSep,(double)(height-BottomSep),ymax,ymin);
        } 
        
        X1=""+MaestroA.rounder(x[0],3);
        X2=""+(int)MaestroA.rounder(x[x.length-1],3);
        X3="|";
        Y1=""+MaestroA.rounder(ymin,3);
        
        if(ymax < 1.0e230){
            if(ymax >= 1.0e-3){
                Y2=""+MaestroA.rounder(ymax,5);
                flag = 0;
            }
            else if(ymax >= 1.0e-4 && ymax < 1.0e-3){
                Y2=""+MaestroA.rounder(ymax*1.0e4,5);
                flag = 4;
            }
            else if(ymax >= 1.0e-5 && ymax < 1.0e-4){
                Y2=""+MaestroA.rounder(ymax*1.0e5,4);
                flag = 5;
            }
            else if(ymax >= 1.0e-6 && ymax < 1.0e-5){
                Y2=""+MaestroA.rounder(ymax*1.0e6,4);
                flag = 6;
            }
            else if(ymax >= 1.0e-7 && ymax < 1.0e-6){
                Y2=""+MaestroA.rounder(ymax*1.0e7,4);
                flag = 7;
            }
            else if(ymax >= 1.0e-8 && ymax < 1.0e-7){
                Y2=""+MaestroA.rounder(ymax*1.0e8,4);
                flag = 8;
            }
            else if(ymax >= 1.0e-9 && ymax < 1.0e-8){
                Y2=""+MaestroA.rounder(ymax*1.0e9,4);
                flag = 9;
            }
            else if(ymax >= 1.0e-10 && ymax < 1.0e-9){
                Y2=""+MaestroA.rounder(ymax*1.0e10,4);
                flag = 10;
            }
            else if(ymax >= 1.0e-11 && ymax < 1.0e-10){
                Y2=""+MaestroA.rounder(ymax*1.0e11,4);
                flag = 11;
            }
            else if(ymax >= 1.0e-12 && ymax < 1.0e-11){
                Y2=""+MaestroA.rounder(ymax*1.0e12,4);
                flag = 12;
            }
            else if(ymax >= 1.0e-13 && ymax < 1.0e-12){
                Y2=""+MaestroA.rounder(ymax*1.0e13,4);
                flag = 13;
            }
            else if(ymax >= 1.0e-14 && ymax < 1.0e-13){
                Y2=""+MaestroA.rounder(ymax*1.0e14,4);
                flag = 14;
            }
            else if(ymax >= 1.0e-15 && ymax < 1.0e-14){
                Y2=""+MaestroA.rounder(ymax*1.0e15,4);
                flag = 14;
            }
            else if(ymax >= 1.0e-16 && ymax < 1.0e-15){
                Y2=""+MaestroA.rounder(ymax*1.0e16,4);
                flag = 16;
            }
            else if(ymax >= 1.0e-17 && ymax < 1.0e-16){
                Y2=""+MaestroA.rounder(ymax*1.0e17,4);
                flag = 17;
            }
            else if(ymax >= 1.0e-18 && ymax < 1.0e-17){
                Y2=""+MaestroA.rounder(ymax*1.0e18,4);
                flag = 18;
            }
            else if(ymax >= 1.0e-19 && ymax < 1.0e-18){
                Y2=""+MaestroA.rounder(ymax*1.0e19,4);
                flag = 19;
            }
            else if(ymax >= 1.0e-20 && ymax < 1.0e-19){
                Y2=""+MaestroA.rounder(ymax*1.0e20,4);
                flag = 20;
            }
            else if(ymax < 1.0e-20){
                Y2=""+ymax;
                flag = 0;
            }
        }
        else{
            Y2="\u221e";
            flag = 0;
        }
        Y3="_";    
    }
    
    protected void plotZeroLine(Graphics g){
        if(ymin*ymax>0){return;}
        FontMetrics fm = g.getFontMetrics();
        g.setFont(font1);
        int yy;
        yy = (int)MaestroA.mapper(0.0,(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
        g.setColor(Color.red);
        g.drawLine(LeftMargin,yy,getSize().width-RightMargin,yy);
        g.drawString("0",LeftMargin-fm.stringWidth("0"),yy+fm.getHeight()/3);
    }
    
    public synchronized void plotZeroLine(boolean Should_Plot_Zero_Line){
        this.Should_Plot_Zero_Line = Should_Plot_Zero_Line;
    }
    
    protected void plotRefPoint(Graphics g){
        int myX=0, myY=0, i;
        i = (int)((NumPoints-1)*(xRef-x[0])/(x[x.length-1]-x[0]));
        if(i<0) {i = 0;}
        if(i>=NumPoints){i=NumPoints-1;}
        myX = (int)MaestroA.mapper(xRef,(double)(getSize().width-RightMargin),(double)(LeftMargin),xmax,xmin);
        if(y[i]>0.0){
            myY = (int)MaestroA.mapper(y[i],(double)TopSep,(double)(getSize().height-BottomSep),ymax,ymin);
        }
        else{
            myY =getSize().height-BottomSep ;
        }
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        g.setColor(Color.white);
        g.drawLine(myX,myY,myX,getSize().height-BottomSep+state.s5);
        
        g.setColor(Color.red);
        MaestroG.fillCircle(myX,myY,state.s5,g);
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    public synchronized void plotRefPoint(boolean Should_Plot_Ref_Point){
        this.Should_Plot_Ref_Point = Should_Plot_Ref_Point;
    }
    
    protected void plotPoints(Graphics g){
        ignition();
        g.setColor(Color.white);
        g.drawPolyline(xx,yy,xx.length);
    }
    
    protected void drawTitle(Graphics g){
        FontMetrics fm = g.getFontMetrics();
        g.setFont(font1);
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        g.setColor(Color.white);
        g.drawString(XLabel,(getSize().width-fm.stringWidth(XLabel))/2+state.s60,getSize().height-BottomSep+3*fm.getHeight()/2+state.s5);
        g.setColor(Color.white);
        g.drawString(TITLE,(getSize().width)*70/100,TopSep/2-state.s2);

        if(type == 1){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripterSymbol("| E","\u03b8"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 2){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| E","R"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 3){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| E","x"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 4){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| E","y"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 5){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| E","z"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 6){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripterSymbol("| H","\u03c6"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 7){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| H","x"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 8){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| H","y"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }

        if(type == 9){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| H","z"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 10){
            g.drawString("V/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripterSymbol("| E","\u03c6"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 11){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripter2("| H","R"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        if(type == 12){
            g.drawString("A/m",LeftMargin-state.s30,getSize().height/2);
            MaestroG.subscripterSymbol("| H","\u03b8"," |",g,state.font14,LeftMargin+state.s13,state.s16);
        }
        
        g.setFont(font1);
        g.setColor(Color.yellow);
        
        g.drawString(X1,LeftMargin-state.s6,getSize().height-BottomSep+3*fm.getHeight()/2);
        g.drawString(X2,getSize().width-RightMargin-fm.stringWidth(X2)+state.s10,getSize().height-BottomSep+3*fm.getHeight()/2);
        g.drawString("180",(getSize().width-RightMargin + LeftMargin-1)/2-state.s7,getSize().height-BottomSep+3*fm.getHeight()/2);
        g.drawString(Y1,state.s10,getSize().height-BottomSep+state.s5);

        // horizontal tick marks.  Using fonts (above) DOES NOT WORK on Mac - Mac sucks!!!!!
        g.drawLine(LeftMargin,getSize().height-BottomSep,LeftMargin,getSize().height-BottomSep+state.s6);
        g.drawLine(LeftMargin+(getSize().width-RightMargin-LeftMargin)/2,getSize().height-BottomSep,
                   LeftMargin+(getSize().width-RightMargin-LeftMargin)/2,getSize().height-BottomSep+state.s6);
        g.drawLine(getSize().width-RightMargin,getSize().height-BottomSep,
                   getSize().width-RightMargin,getSize().height-BottomSep+state.s6);
        g.drawLine(LeftMargin-state.s6,getSize().height-BottomSep,LeftMargin,getSize().height-BottomSep);
        g.drawLine(LeftMargin,TopSep,LeftMargin-state.s6,TopSep);

        if(fm.stringWidth(Y2)>(LeftMargin-state.s10)){
	
            if(flag == 0){
                g.drawString(Y2,state.s5,TopSep-state.s4);    
            }
            else{
                MaestroG.superscripter2(Y2+" 10","-"+flag,"",g,state.font12,state.s5,TopSep-state.s4);
            }
        }
        else{
            if(flag == 0){
		//g.drawString(Y2,Math.max(state.s4,LeftMargin-fm.stringWidth(Y2))-state.s7,TopSep-state.s4);
		// CHEERPJ doesn't render infinity symbol
		if (!Y2.contains(String.valueOf('\u221e'))) {
		    g.drawString(Y2,Math.max(state.s4,LeftMargin-fm.stringWidth(Y2))-state.s7,TopSep-state.s4);
		} else {
		    g.drawImage(infinity,Math.max(state.s4,LeftMargin-fm.stringWidth(Y2))-state.s7,
				TopSep-state.s4-infinity.getHeight(),this);
		}
            }
            else{
                MaestroG.superscripter2(Y2+" 10","-"+flag,"",g,state.font12,LeftMargin+state.s5,TopSep-state.s4);
            }
        }
        /*
        if(fm.stringWidth(Y2)>(LeftMargin-state.s10)){

            if(flag == 0){
                g.drawString(Y2,state.s5,TopSep-state.s4);
            }
            else{

                MaestroG.superscripter2(Y2+" 10","-"+flag,"",g,state.font12,state.s5,TopSep-state.s4);
            }
        }
        else{
            if(flag == 0){
                g.drawString(Y2,state.s4,TopSep-state.s4);    
            }
            else{
                MaestroG.superscripter2(Y2+" 10","-"+flag,"",g,state.font12,state.s5,TopSep-state.s4);
            }
        }
        */
        g.setColor(Color.yellow);    
    }
    
    protected void drawAxis(Graphics g){
        VPos = getSize().height-BottomSep;
        g.setColor(Color.yellow);
        //Vertical Axis
        g.drawLine(LeftMargin,TopSep-state.s1,LeftMargin,getSize().height-BottomSep);
        g.drawLine(LeftMargin,VPos,getSize().width-RightMargin+state.s10,VPos);
        //MaestroG.drawArrow(getSize().width-RightMargin+state.s10,VPos,7,g);
        MaestroG.drawArrowScaled(getSize().width-RightMargin+state.s10,VPos,3,state.sfactor,g);
    }
    
    public final synchronized void setXLabel(String XLabel){
        this.XLabel=XLabel;
    }

    public final synchronized void setYLabel(String YLabel){
        this.YLabel=YLabel;
    } 

    public final synchronized void setTitle(String TITLE){
        this.TITLE = TITLE;
    }

    public final synchronized void setLabels(String TITLE, String YLabel, String XLabel){
        this.TITLE=TITLE;
        this.YLabel = YLabel;
        this.XLabel = XLabel;
    }

    public void plot(double[] xdata, double[] ydata){
        if(NumPoints != xdata.length){
            NumPoints = xdata.length;
            x = new double[NumPoints];
            y = new double[NumPoints];
            xx = new int[NumPoints];
            yy = new int[NumPoints];
        }
        for(int i = 0; i < NumPoints; i++){
            x[i] = xdata[i];
            y[i] = ydata[i];
        }
        repaint();
    }


    public void setPolar(boolean IsPolar){
        this.IsPolar = IsPolar;
    }

    public void setPhiAngle(double phi_angle){
        this.phi_angle=phi_angle;
    }

    public void setType(int type){
        this.type=type;
    }

    public void setYRange(double ymax, double ymin){
        IsYRangeMaxSet=true;
        IsYRangeMinSet=true;
        this.ymax=ymax;
        this.ymin=ymin;
    }

    public void setYRangeMin(double ymin){
        IsYRangeMinSet=true;
        this.ymin=ymin;
    }

    public void setYRangeMax(double ymax){
        IsYRangeMaxSet=true;
        this.ymax=ymax;
    }

    public void setAuto(){
        IsYRangeMaxSet=false;
        IsYRangeMinSet=false;
        IsXRangeMaxSet=false;
        IsXRangeMinSet=false;
    }

    public synchronized void setRefPoint(double xRef){
        this.xRef = xRef;
    }

    public void update(Graphics g){
        paint(g);
    }
    
}
