//import java.applet.*;
//import java.lang.*;

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;

public class PlaneWaveCanvas extends Canvas implements MouseListener, MouseMotionListener, ItemListener{
    PlaneWave_State state;
    InputPanel inputpanel;
    
    private static final Color bgcolor = new Color(255,255,255); // white background
        
    public double xnewmax, xnewmin, ynewmax, ynewmin, xpos, ypos;
    
    private int yshift = 250;
    private int LeftMargin=90, RightMargin=85, TopMargin=60, BottomMargin=210;
    
    private Image im;
    private Graphics buf;
    public int x_Center, y_Center;
   
    //---------------------------------------------------
    private double xpos_old, ypos_old; 
    private int xxpos, yypos, xxpos_old, yypos_old, xxpos_0, yypos_0;
    //---------------------------------------------------
    
    private boolean IsTraceOn, IsFieldOn, IsCleanUpOn, IsDynamic, IsStop, IsStart, IsReset;
    
    public PlaneWaveCanvas(PlaneWave_State state, InputPanel inputpanel){
	super();
	setBackground(bgcolor);
        this.state = state;
        this.inputpanel = inputpanel;
        
        yshift = state.s250;
        LeftMargin = state.s90;
        RightMargin = state.s85;
        TopMargin = state.s60;
        BottomMargin = state.s200+state.s10;
    
	IsTraceOn = false;
        IsFieldOn = true;
	IsCleanUpOn = false;
	IsDynamic = false;
	IsStop = true;
        IsStart = false;
        IsReset = true;
        
        //Center point
        x_Center = state.s300;
        y_Center = state.s300;
        
        xnewmax = 0.1;
	xnewmin = -0.1;
	ynewmax = 0.1;
	ynewmin = -0.1;
        
        xpos = 0.0;
        ypos = 0.0;
        
        this.addMouseListener(this);
	this.addMouseMotionListener(this);
    }
    
    public void mouseDragged(MouseEvent evt){cricket_3(evt);}
    public void mouseMoved(MouseEvent evt){;}//cricket_1(evt);}
    public void mouseClicked(MouseEvent evt){cricket_1(evt);}
    public void mouseEntered(MouseEvent evt){;} 
    public void mouseExited(MouseEvent evt){;}
    public void mousePressed(MouseEvent evt){cricket_1(evt);}
    public void mouseReleased(MouseEvent evt){cricket_1(evt);}
    public void itemStateChanged(ItemEvent evt){;}
    
    private  void cricket_1(MouseEvent evt){

	int x, y, xProbe, yProbe;
        double xtest, ytest;
	x=evt.getX();
	y=evt.getY();
	Graphics g = this.getGraphics();
	
        if(x < state.s600 && x > 0 && y < state.s600 && y > 0){
            xProbe = x - x_Center;
            yProbe = y - y_Center;
        }
        else{
            
            if (x <= 0 && y <= 0){x = 0; y = 0;} 
            else if (x <= 0 && y >= state.s600){x = 0; y = state.s600;}
            else if (x >= state.s600 && y <= 0){x = state.s600; y = 0;}
            else if (x >= state.s600 && y >= state.s600){x = state.s600; y = state.s600;} 
            else if (x <= 0){x = 0;}
            else if (x >= state.s600){x = state.s600;}
            else if (y <= 0){y = 0;}
            else if (y >= state.s600){y = state.s600;}
              
        }
            xProbe = x - x_Center;
            yProbe = y - y_Center;
        
        xtest = xProbe * state.xmax/x_Center;
        ytest = yProbe * state.ymax/y_Center;
        
        if(IsReset){
            state.xpos = MaestroA.rounder(xtest,3);
            state.ypos = MaestroA.rounder(ytest,3);
            state.xpos_0 = MaestroA.rounder(xtest,3);
            state.ypos_0 = MaestroA.rounder(ytest,3);
            state.xpos_old = state.xpos;
            state.ypos_old = state.ypos;
            xxpos = x;
            yypos = y;
            xxpos_old = x;
            yypos_old = y;
            xxpos_0 = x;
            yypos_0 = y;
            repaint();
            
            inputpanel.sliderx0.setValue((int)((state.xpos + state.xmax)/state.Deltax));
            inputpanel.slidery0.setValue((int)((state.ypos + state.ymax)/state.Deltax));
            inputpanel.repaint();
        }
    }
    
    private  void cricket_3(MouseEvent evt){

	int x, y, xProbe, yProbe;
        double xtest, ytest;
	x=evt.getX();
	y=evt.getY();
	Graphics g = this.getGraphics();
	
        if(x < state.s600 && x > 0 && y < state.s600 && y > 0){
            xProbe = x - x_Center;
            yProbe = y - y_Center;
        }
        else{
            
            if (x <= 0 && y <= 0){x = 0; y = 0;} 
            else if (x <= 0 && y >= state.s600){x = 0; y = state.s600;}
            else if (x >= state.s600 && y <= 0){x = state.s600; y = 0;}
            else if (x >= state.s600 && y >= state.s600){x = state.s600; y = state.s600;} 
            else if (x <= 0){x = 0;}
            else if (x >= state.s600){x = state.s600;}
            else if (y <= 0){y = 0;}
            else if (y >= state.s600){y = state.s600;}
              
        }
            xProbe = x - x_Center;
            yProbe = y - y_Center;
        
        xtest = xProbe * state.xmax/x_Center;
        ytest = yProbe * state.ymax/y_Center;
        
        if(IsReset){
            state.xpos = MaestroA.rounder(xtest,3);
            state.ypos = MaestroA.rounder(ytest,3);
            state.xpos_0 = MaestroA.rounder(xtest,3);
            state.ypos_0 = MaestroA.rounder(ytest,3);
            state.xpos_old = state.xpos;
            state.ypos_old = state.ypos;
            xxpos = x;
            yypos = y;
            xxpos_old = x;
            yypos_old = y;
            xxpos_0 = x;
            yypos_0 = y;
            
            repaint();
        }
    }
    
    public void paint(Graphics g){
	if(im == null){
	    im = createImage(getSize().width,getSize().height);
	    buf = im.getGraphics();
	    drawGraph(buf);
	}
	else{
            drawGraph(buf);
	}
	g.drawImage(im,0,0,null);
    }
    
    public void drawGraph(Graphics g){
	//g.draw3DRect(0,0,getSize().width-1,getSize().height-1,false);
	
	//this cleans the trajectory
	if(!IsTraceOn){g.clearRect(0,0,getSize().width,getSize().height);}
	if(IsReset){g.clearRect(0,0,getSize().width,getSize().height);}
        
        drawAxis(g);
        //drawStart(g);
	drawPoints(g,1);
	
    }
    
    public synchronized void ignition(){
        
        xxpos_0 = (int)MaestroA.mapper(state.xpos_0,0,(double)getSize().width,xnewmin,xnewmax);
        yypos_0 = (int)MaestroA.mapper(state.ypos_0,0,(double)getSize().height,ynewmin,ynewmax);
        
        xxpos_old = (int)MaestroA.mapper(xpos_old,0,(double)getSize().width,xnewmin,xnewmax);
        yypos_old = (int)MaestroA.mapper(ypos_old,0,(double)getSize().height,ynewmin,ynewmax);
        
        xxpos = (int)MaestroA.mapper(xpos,0,(double)getSize().width,xnewmin,xnewmax);
        yypos = (int)MaestroA.mapper(ypos,0,(double)getSize().height,ynewmin,ynewmax);
        
    }   
    
    
    private synchronized void drawAxis(Graphics g){
	
        Graphics2D g2d = (Graphics2D)g;
        int rule; 
        float alpha;
        rule = AlphaComposite.SRC_OVER;            
        
        //vertical lines
        Color line1 = new Color(240,240,240);
        Color line2 = new Color(225,200,255);
        
        //int my_step = state.s30;
        int my_step = (int)Math.ceil(state.sfactor*600/20.0);
        
        for(int i = 1; i < 10; i++){
            if(i!=5){g.setColor(line1);}
            else{g.setColor(line2);}
            g.drawLine(i*my_step,0,i*my_step,getSize().height);
        }
        for(int i = 11; i < 20; i++){
            if(i!=15){g.setColor(line1);}
            else{g.setColor(line2);}
            g.drawLine(i*my_step,0,i*my_step,getSize().height);
        }
        for(int i = 1; i < 10; i++){
            if(i!=5){g.setColor(line1);}
            else{g.setColor(line2);}
            g.drawLine(0,i*my_step,getSize().width,i*my_step);
        }
        for(int i = 11; i < 20; i++){
            if(i!=15){g.setColor(line1);}
            else{g.setColor(line2);}
            g.drawLine(0,i*my_step,getSize().width,i*my_step);
        }
            
        g.setColor(Color.lightGray);
        //x axis
        g.drawLine(1,getSize().height/2,getSize().width-state.s2,getSize().height/2);
        drawArrowScaled(getSize().width-state.s10,getSize().height/2,7,state.sfactor,g);
        //y axis
        g.drawLine(getSize().width/2,state.s1,getSize().width/2,getSize().height-state.s2);
        drawArrowScaled(getSize().width/2,getSize().height-state.s10,10,state.sfactor,g);
        
        //z axis
        // Draw center marker for z-axis going into plane (cross)
        g.setColor(Color.white);
        MaestroG.fillCircle(getSize().width/2,getSize().height/2,state.s8,g);
        g.setColor(Color.lightGray);
        MaestroG.drawCircle(getSize().width/2,getSize().height/2,state.s8,g);
        g.drawLine(getSize().width/2-state.s3,getSize().height/2-state.s3,getSize().width/2+state.s3,getSize().height/2+state.s3);
        g.drawLine(getSize().width/2-state.s3,getSize().height/2+state.s3,getSize().width/2+state.s3,getSize().height/2-state.s3);
        
        MaestroG.subscripter("x","","",g,state.font11,getSize().width-state.s12,getSize().height/2-state.s5);
        MaestroG.subscripter("y","","",g,state.font11,getSize().width/2-state.s12,getSize().height-state.s7);
        MaestroG.subscripter("z","","",g,state.font11,getSize().width/2-state.s12,getSize().height/2+state.s12);
        
        if(!IsTraceOn && IsFieldOn){
            // H fields
            int xx = state.s8;
            int xxx = state.s5;
            int step = state.s75;
            //Color newgray = new Color(230,230,230);
            Color newgray = new Color(190,190,190);

            if(state.Hz == 0.0){}
            else if(state.Hz > 0.0){
                g.setColor(newgray);
                MaestroG.subscripter("H","z","",g,state.font16,step-45*xx/10,step);

                for(int i = 0; i < 4; i++){
                    for(int j = 0; j < 4; j++){
                        g.setColor(Color.white);
                        MaestroG.fillCircle(step+step*2*i,step+step*2*j,2*xx,g);
                        g.setColor(newgray);
                        MaestroG.drawCircle(step+step*2*i,step+step*2*j,2*xx,g);
                        g.drawLine(step+step*2*i-xxx,step+step*2*j-xxx,step+step*2*i+xxx,step+step*2*j+xxx);
                        g.drawLine(step+step*2*i-xxx,step+step*2*j+xxx,step+step*2*i+xxx,step+step*2*j-xxx);
                    }
                }
            }
            else{
                for(int i = 0; i < 4; i++){
                    for(int j = 0; j < 4; j++){
                        g.setColor(Color.white);
                        MaestroG.fillCircle(step+step*2*i,step+step*2*j,2*xx,g);
                        g.setColor(newgray);
                        MaestroG.drawCircle(step+step*2*i,step+step*2*j,2*xx,g);
                        MaestroG.fillCircle(step+step*2*i,step+step*2*j,2*xx/3,g);
                    }
                }
            }

            
            
            //E fields
            double EgoX, EgoY, Etest, Mtest, Elength, Mlength;
            double EFX, EFY;
            double BFX, BFY;
            double angle, angle1, angle2, length, length2, lengthE, lengthM, stem;
            double angleB, angleB1, angleB2;
            angle = Math.atan(state.Ey/state.Ex);
            angleB = Math.atan(state.MFy/state.MFx);
            
            length = (double)state.s15;
            length2 = (double)state.s25;
            stem = (double)state.s60;
            
            Etest = Math.sqrt(state.EleFx*state.EleFx + state.EleFy*state.EleFy);
            Mtest = Math.sqrt(state.MFx*state.MFx + state.MFy*state.MFy);
            //if(Etest >= Mtest){
                Elength = stem;
                Mlength = Elength * Mtest/Etest;
                if(Mlength > 150.0){Mlength = 150.0;}
                if(Etest == 0.0){Mlength = stem;}
                
                lengthE = length * Elength/stem;
                lengthM = length * Mlength/stem;
                if(lengthE > length){lengthE = length;}
                if(lengthM > length){lengthM = length;}
                
            //}
            //else{
              //  Mlength = stem;
              //  Elength = Mlength * Etest/Mtest;
              //  lengthE = length * Elength/stem;
              //  lengthM = length * Mlength/stem;
            //}
            
            
            if(state.Ex > 0.0){
                EgoX = Math.abs(Math.cos(angle))*length2;
                EFX = Math.abs(Math.cos(angle))*Elength;
            }
            else{
                EgoX = -Math.abs(Math.cos(angle))*length2;
                EFX = -Math.abs(Math.cos(angle))*Elength;
            }
            if(state.Ey > 0.0){
                EgoY = Math.abs(Math.sin(angle))*length2;
                EFY = Math.abs(Math.sin(angle))*Elength;
            }
            else{
                EgoY = -Math.abs(Math.sin(angle))*length2;
                EFY = -Math.abs(Math.sin(angle))*Elength;
            }
            
            if(state.MFx > 0.0){
                BFX = -Math.abs(Math.cos(angleB))*Mlength;
            }
            else{
                BFX = Math.abs(Math.cos(angleB))*Mlength;
            }
            if(state.MFy > 0.0){
                BFY = -Math.abs(Math.sin(angleB))*Mlength;
            }
            else{
                BFY = Math.abs(Math.sin(angleB))*Mlength;
            }
            
            angle1 = angle + Math.PI/10;
            angle2 = angle - Math.PI/10;
            
            angleB1 = angleB + Math.PI/10;
            angleB2 = angleB - Math.PI/10;
            
            double x1=(double)state.s150;
            double y1=(double)state.s150;
            double x2=(double)state.s450; 
            double y2=(double)state.s150;
            double x3=(double)state.s150;
            double y3=(double)state.s450;
            double x4=(double)state.s450; 
            double y4=(double)state.s450;
            
            drawLineThick(g,x1-EgoX,y1-EgoY,x1+EgoX,y1+EgoY,state.s2,newgray);
            
            if(state.Ex == 0.0 && state.Ey == 0.0){}
            else{
                if(state.Ex >= 0.0 && state.Ey >= 0.0){
                    MaestroG.subscripter("E","","",g,state.font16,(int)(x1+state.s10),(int)(y1-state.s10));
                }
                else if(state.Ex >= 0.0 && state.Ey <= 0.0){
                    MaestroG.subscripter("E","","",g,state.font16,(int)(x1+state.s10),(int)(y1+state.s20));
                }
                else if(state.Ex <= 0.0 && state.Ey >= 0.0){
                    MaestroG.subscripter("E","","",g,state.font16,(int)(x1-state.s20),(int)(y1-state.s10));
                }
                else if(state.Ex <= 0.0 && state.Ey <= 0.0){
                    MaestroG.subscripter("E","","",g,state.font16,(int)(x1-state.s20),(int)(y1+state.s20));
                }
            }

            if(state.Ex >= 0.0){
                g.setColor(newgray);        
                drawLineThick(g,x1+EgoX,y1+EgoY,x1+EgoX-length*Math.cos(angle1),y1+EgoY-length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x1+EgoX,y1+EgoY,x1+EgoX-length*Math.cos(angle2),y1+EgoY-length*Math.sin(angle2),2,newgray);
            }
            else{
                drawLineThick(g,x1+EgoX,y1+EgoY,x1+EgoX+length*Math.cos(angle1),y1+EgoY+length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x1+EgoX,y1+EgoY,x1+EgoX+length*Math.cos(angle2),y1+EgoY+length*Math.sin(angle2),2,newgray);
            }

            drawLineThick(g,x2-EgoX,y2-EgoY,x2+EgoX,y2+EgoY,2,newgray);
            if(state.Ex >= 0.0){
                drawLineThick(g,x2+EgoX,y2+EgoY,x2+EgoX-length*Math.cos(angle1),y2+EgoY-length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x2+EgoX,y2+EgoY,x2+EgoX-length*Math.cos(angle2),y2+EgoY-length*Math.sin(angle2),2,newgray);
            }
            else{
                drawLineThick(g,x2+EgoX,y2+EgoY,x2+EgoX+length*Math.cos(angle1),y2+EgoY+length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x2+EgoX,y2+EgoY,x2+EgoX+length*Math.cos(angle2),y2+EgoY+length*Math.sin(angle2),2,newgray);
            }

            drawLineThick(g,x3-EgoX,y3-EgoY,x3+EgoX,y3+EgoY,2,newgray);
            if(state.Ex >= 0.0){
                drawLineThick(g,x3+EgoX,y3+EgoY,x3+EgoX-length*Math.cos(angle1),y3+EgoY-length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x3+EgoX,y3+EgoY,x3+EgoX-length*Math.cos(angle2),y3+EgoY-length*Math.sin(angle2),2,newgray);
            }
            else{
                drawLineThick(g,x3+EgoX,y3+EgoY,x3+EgoX+length*Math.cos(angle1),y3+EgoY+length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x3+EgoX,y3+EgoY,x3+EgoX+length*Math.cos(angle2),y3+EgoY+length*Math.sin(angle2),2,newgray);
            }

            drawLineThick(g,x4-EgoX,y4-EgoY,x4+EgoX,y4+EgoY,2,newgray);
            if(state.Ex >= 0.0){
                drawLineThick(g,x4+EgoX,y4+EgoY,x4+EgoX-length*Math.cos(angle1),y4+EgoY-length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x4+EgoX,y4+EgoY,x4+EgoX-length*Math.cos(angle2),y4+EgoY-length*Math.sin(angle2),2,newgray);
            }
            else{
                drawLineThick(g,x4+EgoX,y4+EgoY,x4+EgoX+length*Math.cos(angle1),y4+EgoY+length*Math.sin(angle1),2,newgray);
                drawLineThick(g,x4+EgoX,y4+EgoY,x4+EgoX+length*Math.cos(angle2),y4+EgoY+length*Math.sin(angle2),2,newgray);
            }
            
            drawStart(g);
            
            // draw field vectors at particle
            if(state.particle == 1){
                drawLineThick(g,xxpos-EFX,yypos-EFY,xxpos,yypos,2,Color.red);
                if(state.Ex >= 0.0){
                    drawLineThick(g,xxpos-EFX,yypos-EFY,xxpos-EFX+lengthE*Math.cos(angle1),yypos-EFY+lengthE*Math.sin(angle1),2,Color.red);
                    drawLineThick(g,xxpos-EFX,yypos-EFY,xxpos-EFX+lengthE*Math.cos(angle2),yypos-EFY+lengthE*Math.sin(angle2),2,Color.red);
                }
                else{
                    drawLineThick(g,xxpos-EFX,yypos-EFY,xxpos-EFX-lengthE*Math.cos(angle1),yypos-EFY-lengthE*Math.sin(angle1),2,Color.red);
                    drawLineThick(g,xxpos-EFX,yypos-EFY,xxpos-EFX-lengthE*Math.cos(angle2),yypos-EFY-lengthE*Math.sin(angle2),2,Color.red);
                }
                
                drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos,yypos,2,Color.blue);
                if(state.MFx > 0.0){
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB1),yypos-BFY-lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB2),yypos-BFY-lengthM*Math.sin(angleB2),2,Color.blue);
                }
                else if(state.MFx < 0.0){
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB1),yypos-BFY+lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB2),yypos-BFY+lengthM*Math.sin(angleB2),2,Color.blue);
                } 
                else if(state.MFx == 0.0 && state.MFy > 0.0 && state.vx > 0.0){
                    //System.out.println("CASE A"+state.MFy);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB1),yypos-BFY+lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB2),yypos-BFY+lengthM*Math.sin(angleB2),2,Color.blue);
                }
                else if(state.MFx == 0.0 && state.MFy > 0.0 && state.vx < 0.0){
                    //System.out.println("CASE A"+state.MFy);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB1),yypos-BFY-lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB2),yypos-BFY-lengthM*Math.sin(angleB2),2,Color.blue);
                }
                else if(state.MFx == 0.0 && state.MFy < 0.0 && state.vx < 0.0){
                    //System.out.println("CASE A"+state.MFy);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB1),yypos-BFY+lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB2),yypos-BFY+lengthM*Math.sin(angleB2),2,Color.blue);
                }
                else if(state.MFx == 0.0 && state.MFy < 0.0 && state.vx > 0.0){
                    //System.out.println("CASE A"+state.MFy);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB1),yypos-BFY-lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB2),yypos-BFY-lengthM*Math.sin(angleB2),2,Color.blue);
                }   
            }
            else if(state.particle == 2){
                drawLineThick(g,xxpos,yypos,xxpos+EFX,yypos+EFY,2,Color.red);
                if(state.Ex >= 0.0){
                    drawLineThick(g,xxpos+EFX,yypos+EFY,xxpos+EFX-lengthE*Math.cos(angle1),yypos+EFY-lengthE*Math.sin(angle1),2,Color.red);
                    drawLineThick(g,xxpos+EFX,yypos+EFY,xxpos+EFX-lengthE*Math.cos(angle2),yypos+EFY-lengthE*Math.sin(angle2),2,Color.red);
                }
                else{
                    drawLineThick(g,xxpos+EFX,yypos+EFY,xxpos+EFX+lengthE*Math.cos(angle1),yypos+EFY+lengthE*Math.sin(angle1),2,Color.red);
                    drawLineThick(g,xxpos+EFX,yypos+EFY,xxpos+EFX+lengthE*Math.cos(angle2),yypos+EFY+lengthE*Math.sin(angle2),2,Color.red);
                }
                
                //drawLineThick(g,xxpos+BFX,yypos+BFY,xxpos,yypos,2,Color.blue);
                drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos,yypos,2,Color.blue);
                if(state.MFx > 0.0){
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB1),yypos-BFY-lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX-lengthM*Math.cos(angleB2),yypos-BFY-lengthM*Math.sin(angleB2),2,Color.blue);
                }
                else{
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB1),yypos-BFY+lengthM*Math.sin(angleB1),2,Color.blue);
                    drawLineThick(g,xxpos-BFX,yypos-BFY,xxpos-BFX+lengthM*Math.cos(angleB2),yypos-BFY+lengthM*Math.sin(angleB2),2,Color.blue);
                }           
            }
            else if(state.particle == 3){}
            
        }
        
        //frame
        g.setColor(Color.black);
	g.draw3DRect(0,0,getSize().width-1,getSize().height-1,false);
    }
    
    private synchronized void drawPoints(Graphics g, int tipo){
        Graphics2D g2d = (Graphics2D)g;
        switch(tipo){
	    case 1:
		//if(IsTraceOn){
                    //g.setColor(Color.red);
                    //MaestroG.fillCircle(xxpos_0,yypos_0,9,g);
                    //g.setColor(Color.pink.brighter());
                    //MaestroG.fillCircle(xxpos_0-1,yypos_0-1,2,g);
                    
                    g.setColor(Color.black);
                    MaestroG.fillCircle(xxpos,yypos,state.s9,g);
                    g.setColor(Color.white);
                    MaestroG.fillCircle(xxpos-state.s1,yypos-state.s1,state.s2,g);
		//}
		//else{
                  //  g.setColor(Color.red);
                  //  MaestroG.fillCircle(xxpos_0,yypos_0,9,g);
                  //  g.setColor(Color.pink);
                  //  MaestroG.fillCircle(xxpos_0-1,yypos_0-1,2,g);
                  //  
                  //  g.setColor(Color.green);
		  //  MaestroG.fillCircle(xxpos,yypos,9,g);
                  //  g.setColor(Color.white);
                  //  MaestroG.fillCircle(xxpos-1,yypos-1,2,g);
		//}
		break;
	    case 2:
                g.setColor(bgcolor);
		MaestroG.fillCircle(xxpos,yypos,state.s9,g);
                
                break;
	}
    }
    
    private synchronized void drawStart(Graphics g){
        Graphics2D g2d = (Graphics2D)g;
        g.setColor(Color.red);
        MaestroG.fillCircle(xxpos_0,yypos_0,state.s9,g);
        g.setColor(Color.pink.brighter());
        MaestroG.fillCircle(xxpos_0-state.s1,yypos_0-state.s1,state.s2,g);
    }
    
    private void drawLineThick(Graphics g, double x1, double y1, double x2, double y2, int thick, Color color){
	
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        Line2D.Double line = new Line2D.Double(x1,y1,x2,y2);
        g2d.draw(line);
  
        g2d.setStroke(new BasicStroke(1));
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }

    
    public synchronized void reset(){
	IsTraceOn = true;//false;
	IsCleanUpOn = false;
    }
    
    public synchronized void cleanUp(){
	IsCleanUpOn=true;
    }
    
    public synchronized void setTrace(boolean IsTraceOn){
	this.IsTraceOn = IsTraceOn;
    }
    
    public synchronized void setField(boolean IsFieldOn){
	this.IsFieldOn = IsFieldOn;
    }
    
    public synchronized void setDynamics(boolean IsDynamic){
	this.IsDynamic = IsDynamic;
    }

    
    public void update(Graphics g){
	
        if(!IsDynamic){
	    paint(g);
	    return;
	}
	if(IsDynamic && IsTraceOn){g.clipRect(LeftMargin+1,TopMargin+1,WIDTH-1,HEIGHT-1);}
	if(IsCleanUpOn){
	    g.clearRect(0,0,getSize().width,getSize().height);
	    IsCleanUpOn = false;
	    drawAxis(g);
	}
        if(!IsTraceOn){
	    drawPoints(g,2);//This cleans the previous graph
	}
        //drawStart(g);
	drawPoints(g,1);//This draws the new graph
	drawAxis(g);
    }
    
    //private void clean_memory(){}
    
    public synchronized void setMargins(int LeftMargin, int RightMargin, int TopMargin, int BottomMargin){
	this.LeftMargin = LeftMargin;
	this.RightMargin = RightMargin;
	this.TopMargin = TopMargin;
	this.BottomMargin = BottomMargin;
    }
    
    public synchronized void setPositions(double xpos, double ypos, double xpos_old, double ypos_old){
        this.xpos = xpos;
        this.ypos = ypos;
        this.xpos_old = xpos_old;
        this.ypos_old = ypos_old;
    }
    
    public synchronized void setNewBoundaries(double xnewmax, double ynewmax, double xnewmin, double ynewmin){
        this.xnewmax = xnewmax;
        this.ynewmax = ynewmax;
        this.xnewmin = xnewmin;
        this.ynewmin = ynewmin;
    }
    
    public synchronized void setStop(boolean IsStop){
        this.IsStop = IsStop;
    }
    
    public synchronized void setStart(boolean IsStart){
        this.IsStart = IsStart;
    }
    
    public synchronized void setReset(boolean IsReset){
        this.IsReset = IsReset;
    }
    
    public void drawArrowScaled(int x, int y, int tipo, double sfactor, Graphics g){
	Graphics2D g2d = (Graphics2D)g;
        double s;
        s = sfactor;
        
        switch (tipo){
	   
          case 1://ArrowUpSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y,x,y-(int)(s*8));
		//draw oblique arrow head
		Polygon pH = new Polygon();
		pH.addPoint(x-(int)(s*2), y-(int)(s*2));
		pH.addPoint(x+(int)(s*2), y-(int)(s*2));
		pH.addPoint(x,y-(int)(s*8));
		g.drawPolygon(pH);
		g.fillPolygon(pH);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
          break;
          
          case 2://ArrowDownSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y,x,y+(int)(s*8));
		//draw oblique arrow head
		Polygon pJ = new Polygon();
		pJ.addPoint(x-(int)(s*2), y+(int)(s*2));
		pJ.addPoint(x+(int)(s*2), y+(int)(s*2));
		pJ.addPoint(x,y+(int)(s*8));
		g.drawPolygon(pJ);
		g.fillPolygon(pJ);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   break;
           
           case 3://ArrowRightSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y,x+(int)(s*8),y);
		//draw oblique arrow head
		Polygon pK = new Polygon();
		pK.addPoint(x+(int)(s*2), y-(int)(s*2));
		pK.addPoint(x+(int)(s*2), y+(int)(s*2));
		pK.addPoint(x+(int)(s*8),y);
		g.drawPolygon(pK);
		g.fillPolygon(pK);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   
	   break;
           
           case 4://ArrowLeftSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                g.drawLine(x,y,x-(int)(s*8),y);
		//draw oblique arrow head
		Polygon pL = new Polygon();
		pL.addPoint(x-(int)(s*2), y-(int)(s*2));
		pL.addPoint(x-(int)(s*2), y+(int)(s*2));
		pL.addPoint(x-(int)(s*8),y);
		g.drawPolygon(pL);
		g.fillPolygon(pL);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
 
	   break;
           
           case 5://ArrowOblique 45 degrees NE
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
		//draw oblique arrow head
		Polygon pM = new Polygon();
                //draw oblique arrow head
                
                pM.addPoint(x+(int)(s*5),y-(int)(s*5));
		pM.addPoint(x-(int)(s*1),y-(int)(s*2));
		pM.addPoint(x+(int)(s*2),y+(int)(s*1));
		
                g.drawPolygon(pM);
		g.fillPolygon(pM);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
                 
           break;
           case 7://Larger ArrowRightSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                //g.drawLine(x,y,x+(int)(s*10),y);
		
		Polygon pR = new Polygon();
		pR.addPoint(x, y-(int)(s*3));
		pR.addPoint(x, y+(int)(s*3));
		pR.addPoint(x+(int)(s*7),y);
		g.drawPolygon(pR);
		g.fillPolygon(pR);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   
	   break;
           
           case 8://Larger ArrowLeftSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                //g.drawLine(x,y,x-(int)(s*10),y);
		
		Polygon pS = new Polygon();
		pS.addPoint(x, y-(int)(s*3));
		pS.addPoint(x, y+(int)(s*3));
		pS.addPoint(x-(int)(s*7),y);
		g.drawPolygon(pS);
		g.fillPolygon(pS);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
 
	   break;
           
           case 9://ArrowUpSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                //g.drawLine(x,y,x,y-(int)(s*10));
		
		Polygon pU = new Polygon();
		pU.addPoint(x-(int)(s*3), y);
		pU.addPoint(x+(int)(s*3), y);
		pU.addPoint(x,y-(int)(s*7));
		g.drawPolygon(pU);
		g.fillPolygon(pU);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        
          break;
          
          case 10://ArrowDownSmooth
               g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
                //g.drawLine(x,y,x,y-(int)(s*10));
		
                Polygon pD = new Polygon();
                pD.addPoint(x-(int)(s*3), y);
		pD.addPoint(x+(int)(s*3), y);
		pD.addPoint(x,y+(int)(s*7));
		g.drawPolygon(pD);
		g.fillPolygon(pD);
                
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
	   break;
           
           
	}		
    }
}
