//VectorCanvas.java
// A Canvas for drawing of a basic 3D environment

import java.awt.*;
import java.awt.geom.*;
//import java.awt.geom.Arc2D.Double;
import java.awt.image.*;
import java.net.*;
import java.awt.event.*;
import java.util.*;

public final class VectorCanvas extends Canvas implements Runnable, MouseListener, MouseMotionListener {
  private static Projection projector;             
  public int xref;
  public int yref;
  
  public boolean enter_E = false;
  
  public int latitude = 90;
  public int longitude = 45;
  public double distance = 0.5;   // [m]
  public double WireLength = 0.5; // [m]
  public double exponent = 1.0;
  public double tops = 1.0;
  public boolean ShowLabels = true;
  
  public double scale_factor = 200.0;
  public double scale_H = 10.0;
  
  public double radius_loop = 0.05; //meters
  public double z_H = 0.5; //meters
  public double Current = 1.0; // Amperes
  public double Current1 = 1.0; // Amperes
  public double Current2 = 1.0; // Amperes
  public double B1, B2, F1, F2, F1prime, F2prime;
  
  public double RVector, deltaH, deltaHx, deltaHz; 
  public double angle_thetaH;
  
  //  VALUES HERE
  public double k_magnitude; // wave vector magnitude
  public double kx, ky, kz; // wave vector components
  
  // VALUES after rotations ====================================================
  public double kintx, kinty, kintz;
  public double Eintx, Einty, Eintz;
  public double Hintx, Hinty, Hintz;
  
  public double knewx, knewy, knewz;
  public double Enewx, Enewy, Enewz;
  public double Hnewx, Hnewy, Hnewz;
  //============================================================================
  
  public double kx_norm, ky_norm, kz_norm, k_ref, Ex_norm, Ey_norm, Ez_norm, E_ref, Hx_norm, Hy_norm, Hz_norm, H_ref;
  public double Efactor, Hfactor, labfact, labfactk;
  public double kxy_magnitude; double psi_angle;
      
  public double theta_rate, phi_rate, phi_rateE; //for conversion from sliders to k-vector reference angles 
  public double E_intermediate;
  public double E_magnitude; // E vector magnitude
  public double H_magnitude; // H vector magnitude
  public double H_max, dH_max; // H vector magnitude MAXIMUM
  public double Ex, Ey, Ez; // Electric field components
  public double Hx, Hy, Hz; // Magnetic field components
  
  public double medium_impedance; // Ohms
  
  public double angular_distance;
  public double epsilon_r, mu_r;
  //private static final double epsilon0 = 8.8541878176E-12; // Units: F/m  exact value
  public static final double epsilon0 = 8.841941286E-12; //8.8541878176E-12; //Units: F/m  Approximate value
  public static final double mu0 = 1.25663706144E-6; //Units H/m
  public static final double mu0_norm = 1.25663706144; //Units H/m
  public double light_velocity = Math.sqrt(1.0/(epsilon0*mu0)); //  Units m/s
  
  //public boolean IsPatchOn = true;
  public boolean IsPatchOn = false;
  public Color color_line = Color.gray;
  public Color color_line1 = Color.black;
  public Color color_line2 = Color.gray;
  public Color color_line3 = Color.red;
  
  public Color Color_kvec = Color.black;
  public Color Color_Evec = Color.red;
  public Color Color_Hvec = Color.blue;
  
  private Image im;
  private Graphics buf;
  
  // constants           
  private static final int TOP    = 0;
  private static final int CENTER = 1;
  //----------------------------------------------------------------------------

  VectorCanvas() {
    super();
        
    projector = new Projection();
    
    //--------------------------------------------------------------------------
    // This scales the viewing distance
    // Sets "new_distance" in Projection.java
    projector.setDistance(70);
    
    // This scales the picture with respect to the canvs
    // Sets "_2D_scale" in Projection_java
    projector.set2DScaling(13);
    
    // In Projection.java: factor = new_distance * _2D_scale
    
    //--------------------------------------------------------------------------
    //These set angles for initial condition of the x,y,z axes
    projector.setAzimuthAngle(60);//(30);
    projector.setElevationAngle(15);//polar angle, actually z axis is reference...
    
    //--------------------------------------------------------------------------
    
    epsilon_r = 1.0;
    mu_r = 1.0;
    
    z_H = distance;
    phi_rate = 0.0; //0.125;
    
    H_magnitude = Current*radius_loop*radius_loop/(2.0*Math.pow((radius_loop*radius_loop+z_H*z_H),1.5)); // A/m
    H_max = Current/(2.0*radius_loop); // A/m
    dH_max = Current/(4.0*Math.PI*radius_loop*radius_loop);
    RVector = Math.sqrt(radius_loop * radius_loop + z_H * z_H);
    deltaH = Current*radius_loop/(4.0*Math.PI*Math.pow((radius_loop*radius_loop+z_H*z_H),1.5));
    angle_thetaH = Math.acos(radius_loop/(Math.sqrt(radius_loop*radius_loop+z_H*z_H)));
    deltaHx = deltaH * Math.sin(angle_thetaH);
    deltaHz = deltaH * Math.cos(angle_thetaH);
    
      B1 = - mu0_norm*Current1/(2.0*Math.PI*z_H);
      B2 =   mu0_norm*Current2/(2.0*Math.PI*z_H);
      F1 =   mu0_norm*Current1*Current2*WireLength/(2.0*Math.PI*z_H);
      F2 = - mu0_norm*Current1*Current2*WireLength/(2.0*Math.PI*z_H);
      F1prime =   mu0_norm*Current1*Current2/(2.0*Math.PI*z_H);
      F2prime = - mu0_norm*Current1*Current2/(2.0*Math.PI*z_H);
        
    repaint();
    //--------------------------------------------------------------------------
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
   
  }
  
  public void destroyImage() {
    
  }
  
  private boolean dragged;            // dragged flag
  public int     click_x, click_y;    // previous mouse cursor position
  
    public void mouseMoved(MouseEvent evt){;}
    public void mouseEntered(MouseEvent evt){;}
    public void mouseExited(MouseEvent evt){;}
    public void mousePressed(MouseEvent evt){
        int x, y;
	x=evt.getX();
	y=evt.getY();

        click_x = x;
        click_y = y;
        
    }
    
    public void mouseReleased(MouseEvent evt){;}
     
    public void mouseClicked(MouseEvent evt) {
        int x, y;
	x=evt.getX();
	y=evt.getY();

        click_x = x;
        click_y = y;
  }
  
  public void mouseDragged(MouseEvent evt) {
    int x, y, xref, yref;
    
    xref = getSize().width;
    yref = getSize().height;
    x=evt.getX();
    y=evt.getY();
    
    // Clamp x and y to size of Canvas
    if(x<0){x=0;} 
    if(y<0){y=0;} 
    if(x>xref){x=xref;} 
    if(y>yref){y=yref;} 
    
    float new_value = 0.0f;
    //new_value = projector.getAzimuthAngle() + (x - click_x);
    new_value = projector.getAzimuthAngle() + (x - click_x)*360/getSize().width;
    while (new_value > 360) new_value -= 360;
    while (new_value < 0) new_value += 360;
    projector.setAzimuthAngle(new_value);
    
    //System.out.println("Azimuth = "+new_value);
    
    //new_value = projector.getElevationAngle() + (y - click_y);
    new_value = projector.getElevationAngle() + (y - click_y)*180/getSize().height;
    if (new_value > 90){new_value = 90;}
    //if (new_value > 180){new_value = 180;}
    //if (new_value > 30){new_value = 30;}
    else if (new_value < 0){new_value = 0;}
    projector.setElevationAngle(new_value);
    
    //System.out.println("Elevation = "+new_value);
    
    repaint();
    click_x = x;
    click_y = y;
    
  }
  
  public void drawpanel(Graphics g){
        projector.setProjectionArea(new Rectangle(0,0,getSize().width, getSize().height));
        //g.setColor(Color.lightGray);
        //g.setColor(Color.white);
        g.setColor(new Color(250,250,255));
        g.fillRect(0,0,getSize().width,getSize().height); 
        
        drawStuff(g,true);
        
  }
  
  public void paint(Graphics g) {
        
        if(im == null){
		im = createImage(getSize().width,getSize().height);
		buf = im.getGraphics();
		drawpanel(buf);
        }
        else{
		drawpanel(buf);
        }
	
        //repaint();
	g.drawImage(im,0,0,null);
  }

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

  public void run() {
                    
      Graphics g = getGraphics();
      paint(g);
      g.dispose();    
  }
  
/*----------------------------------------------------------------------------------------*
 *                            Private methods begin here                                  *
 *----------------------------------------------------------------------------------------*/

  
  private final void drawStuff(Graphics g, boolean draw_axes) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        Point    projection;   
        int      x[],y[],i,j;
        float    vpos[];
        float    vtip[];
        double   Array[][];
        float    x3D[][], y3D[][], z3D[][];
        double    Patchx1[][], Patchy1[][], Patchx2[][], Patchy2[][], 
                 Patchx3[][], Patchy3[][]; 
        float    xINT[][], yINT[][], zINT[][];
        double    zTest[];
        float    xRef, yRef, zRef;
        double   z3DAux[][];
        float    axisL = 17.0f;
        double   Scale = 15.0;
        Color    colore;
        int      thick1, thick2, thick3, thick4, thick5;
        int      rotx, roty;
        
        thick1 = 1;
        thick2 = 2;
        thick3 = 3;
        thick4 = 4;
        thick5 = 5;

        x = new int[5]; y = new int[5]; vpos = new float[3]; vtip = new float[3];
        
      // transparency set up
      int rule; 
      rule = AlphaComposite.SRC_OVER;
      g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
      
      medium_impedance = Math.sqrt(mu_r*mu0/(epsilon_r*epsilon0));
    
      z_H = distance;
      H_magnitude = Current*radius_loop*radius_loop/(2.0*Math.pow((radius_loop*radius_loop+z_H*z_H),1.5)); // A/m
      H_max = Current/(2.0*radius_loop); // A/m
      dH_max = Current/(4.0*Math.PI*radius_loop*radius_loop);
      
        RVector = Math.sqrt(radius_loop * radius_loop + z_H * z_H);
        //deltaH = Current*radius_loop/(4.0*Math.PI*Math.pow((radius_loop*radius_loop+z_H*z_H),1.5));  // net without radial component
        deltaH = Current/(4.0*Math.PI*(radius_loop*radius_loop+z_H*z_H));
        angle_thetaH = Math.acos(radius_loop/(Math.sqrt(radius_loop*radius_loop+z_H*z_H)));
        deltaHx = deltaH * Math.sin(angle_thetaH);
        deltaHz = deltaH * Math.cos(angle_thetaH);
    
      
      //System.out.println("H_max = "+H_max+"   H_z = "+H_magnitude);
      // dotted circle perpendicular to x
      //draw3DCircleThickX1(g, 0.0, 0.0, 0.0, 16.0, thickH, ColorH);     
      //draw3DCircleThickX2(g, 0.0, 0.0, 0.0, 16.0, thickH, ColorH);
        
      //==============================================================================================
       
      B1 = - mu0_norm*Current1/(2.0*Math.PI*z_H);
      B2 =   mu0_norm*Current2/(2.0*Math.PI*z_H);
      F1 =   mu0_norm*Current1*Current2*WireLength/(2.0*Math.PI*z_H);
      F2 = - mu0_norm*Current1*Current2*WireLength/(2.0*Math.PI*z_H);
      F1prime =   mu0_norm*Current1*Current2/(2.0*Math.PI*z_H);
      F2prime = - mu0_norm*Current1*Current2/(2.0*Math.PI*z_H);
      
      //------------------------------------------------------------------------
      //                               DRAW AXES
      //------------------------------------------------------------------------      
      //draw axes - Length is 20 for x and y, z reference axes
      //------------------------------------------------------------------------
      double axis_ref = 20.0;
      double plusDeg = projector.getAzimuthAngle();
      double plusRad = plusDeg *Math.PI/180.0;
      
      double ywireA; double ywireB;
      ywireA =  2.0 + 14.0 * z_H;
      ywireB = -(2.0 + 14.0 * z_H);
      
      Color ColorHH = new Color(200,200,255); 
      
      g2d.setComposite(AlphaComposite.getInstance(rule, 0.3f));
      // first half
      if(enter_E){draw3DCircleThickZ2(g, 0.0, ywireB, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      else{draw3DCircleThickZ2(g, 0.0, ywireA, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
      
      g2d.setComposite(AlphaComposite.getInstance(rule, 0.3f));
      // second half
      
      if(enter_E){draw3DCircleThickZ1(g, 0.0, ywireB, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      else{draw3DCircleThickZ1(g, 0.0, ywireA, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
      
      
      //------------------------------------------------------------------------
      double B1shift = 0.0;
      double B2shift = 0.0;
      if((plusDeg >= 0.0 && plusDeg <= 180)){
          B2shift = 2.0;
          B1shift = -4.0;
      }
      else{
          B1shift = -2.0;
          B2shift = 4.0;
      }
      
      
      int thickwire = 30;
      int thickwire2 = 5;
      //========================================================================
      double wireLen = 3.0 + 13.0 * WireLength;
      //========================================================================
      double zforce = 1.0;
      Color wire2 = new Color(255, 170, 120);
      Color wire1 = new Color(180, 200, 205);
      Color axis1 = Color.gray;
      Color arrow1 = Color.white;
      Color arrow2 = Color.white;
      Color Forcein = Color.green.darker();
      Color Forceout = Color.red;
      Color Bcolor = Color.blue.darker();
      
      g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
      draw3DVector(g, 0, 20, 0.0, -22.50, wireLen+1, 0.0, -20.50, wireLen+1, 2, axis1);
      draw3DVector(g, 0, 20, 0.0, -22.50, -wireLen-1, 0.0, -20.50, -wireLen-1, 2, axis1);
      
      draw3DVector(g, axisL, 20, 0.0, -21.50, -wireLen-1, 0.0, -21.50, wireLen+1, thick1, axis1);
      // put second arrow on double headed arrow length
      draw3DVector(g, axisL, 20, 0.0, -21.50, -wireLen-0.8, 0.0, -21.50, -wireLen-1, thick1, axis1);
      
      projection = projector.project(0.0f,(float)(-23.0),(float)(1.0));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString(g,(int)(x[0]), (int)(y[0]),"l",Label.LEFT,TOP, axis1);
      
      draw3DVector(g, axisL, 20, 0.0, ywireB/2, wireLen+2, 0.0, ywireB, wireLen+2, thick1, axis1);
      draw3DVector(g, axisL, 20, 0.0, ywireB/2, wireLen+2, 0.0, 0.0, wireLen+2, thick1, axis1);
      draw3DVector(g, axisL, 20, 0.0, ywireA/2, wireLen+2, 0.0, ywireA, wireLen+2, thick1, axis1);
      draw3DVector(g, axisL, 20, 0.0, ywireA/2, wireLen+2, 0.0, 0.0, wireLen+2, thick1, axis1);
      
      projection = projector.project(0.0f,(float)(ywireB/2-0.5),(float)(wireLen+4));     
            x[0] = projection.x; y[0] = projection.y;
            outString2(g,(int)(x[0]), (int)(y[0]),"d/2",Label.LEFT,TOP, axis1);
            
      projection = projector.project(0.0f,(float)(ywireA/2-0.5),(float)(wireLen+4));     
            x[0] = projection.x; y[0] = projection.y;
            outString2(g,(int)(x[0]), (int)(y[0]),"d/2",Label.LEFT,TOP, axis1);
      
      draw3DVector(g, 0, 20, 0.0, ywireB, wireLen+3, 0.0, ywireB, wireLen, thick1, axis1);
      draw3DVector(g, 0, 20, 0.0, ywireA, wireLen+3, 0.0, ywireA, wireLen, thick1, axis1);
     
      projection = projector.project(0.0f,(float)(ywireA),(float)(wireLen+6));     
            x[0] = projection.x; y[0] = projection.y;
            outString3(g,(int)(x[0]), (int)(y[0]),"I","2",Label.LEFT,TOP, Color.red);
            
      projection = projector.project(0.0f,(float)(ywireB),(float)(wireLen+6));     
            x[0] = projection.x; y[0] = projection.y;
            outString3(g,(int)(x[0]), (int)(y[0]),"I","1",Label.LEFT,TOP, Color.red);
            
      
      if((plusDeg >= 0.0 && plusDeg <= 90) || (plusDeg >= 270.0 && plusDeg <= 360)){
            
            draw3DVectorDash(g, 0, 20, 0.0, ywireB-1, 0.0, 0.0, -axis_ref, 0.0, thick1, 5, axis1); // y-axis
            
            if((Current1 > 0 && Current2 < 0) || (Current1 < 0 && Current2 > 0)){
                draw3DVector(g, 50, 30, 0.0, ywireB-1.2, zforce, 0.0, ywireB-5, zforce, 4, Forceout);
                projection = projector.project(0.0f,(float)(ywireB-4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","1",Label.LEFT,TOP, Forceout);
            }
            else if((Current1 > 0 && Current2 > 0) || (Current1 < 0 && Current2 < 0)){
                draw3DVector(g, 50, 30, 0.0, ywireB-5, zforce, 0.0, ywireB-1.2, zforce, 4, Forcein);
                projection = projector.project(0.0f,(float)(ywireB-4),(float)(4.0+zforce));
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","1",Label.LEFT,TOP, Forcein);
            }
            
            g2d.setComposite(AlphaComposite.getInstance(rule, 0.9f));
            draw3DVector(g, 0, 20, 0.0, ywireB, -wireLen, 0.0, ywireB, wireLen, thickwire, wire1);
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
            
            if(!enter_E){
                if(Current2 > 0){
                    draw3DVector(g, 50, 30, -4.0, ywireB+1.5, 0.0, 4.0, ywireB+1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireB+B2shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 2",Label.LEFT,TOP, Bcolor);
                }
                else if(Current2 < 0){
                    draw3DVector(g, 50, 30, 4.0, ywireB+1.5, 0.0, -4.0, ywireB+1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireB+B2shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 2",Label.LEFT,TOP, Bcolor);
                }
            }
            if(Current1 > 0){
                draw3DVector(g, 50, 30, .0, ywireB, wireLen-2.8, 0.0, ywireB, wireLen+0.8, 5, arrow1);
            }
            else if(Current1 < 0){
                draw3DVector(g, 50, 30, 0.0, ywireB, wireLen+0.8, 0.0, ywireB, wireLen-2.8, 5, arrow1);
            } 
            
            draw3DVector(g, 0, 20, 0.0, 0.0, 0.0, 0.0, ywireA-1, 0.0, thick1, axis1); // y-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, 0.0, ywireB+1, 0.0, thick1, 5, axis1); // y-axis
            
            draw3DVector(g, axisL, 20, 0.0, 0.0, 0.0, axis_ref, 0.0, 0.0, thick1, axis1); // x-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, -axis_ref, 0.0, 0.0, thick1, 5, axis1); // x-axis
            projection = projector.project((float)(axis_ref),0.0f,0.0f);     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(x[0]), (int)(y[0]),"x",Label.LEFT,TOP, axis1);
            
            draw3DVector(g, axisL, 20, 0.0, 0.0, 0.0, 0.0, 0.0, axis_ref, thick1, axis1); // z-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, 0.0, 0.0, -axis_ref, thick1, 5, axis1); // z-axis
            projection = projector.project(0.0f,0.0f,(float)(axis_ref));     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(1.03*x[0]), (int)(y[0]),"z",Label.LEFT,CENTER, axis1);
            
            if(enter_E){
                if(Current1 > 0){
                    draw3DVector(g, 50, 30, 4.0, ywireA-1.5, 0.0, -4.0, ywireA-1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireA+B1shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 1",Label.LEFT,TOP, Bcolor);
                }
                else if(Current1 < 0){
                    draw3DVector(g, 50, 30, -4.0, ywireA-1.5, 0.0, 4.0, ywireA-1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireA+B1shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 1",Label.LEFT,TOP, Bcolor);
                }
            }
            
            g2d.setComposite(AlphaComposite.getInstance(rule, 0.9f));
            draw3DVector(g, 0, 20, 0.0, ywireA, -wireLen, 0.0, ywireA, wireLen, thickwire, wire2);
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
            
            if(Current2 > 0){
                draw3DVector(g, 50, 30, 0.0, ywireA, wireLen-2.8, 0.0, ywireA, wireLen+0.8, 5, arrow2);
            }
            else if(Current2 < 0){
                draw3DVector(g, 50, 30, 0.0, ywireA, wireLen+0.8, 0.0, ywireA, wireLen-2.8, 5, arrow2);
            }
            
            // portion of y-axis in the front with label;
            draw3DVector(g, axisL, 20, 0.0, ywireA+1, 0.0, 0.0, axis_ref, 0.0, thick1, axis1); // y-axis
            projection = projector.project(0.0f,(float)(axis_ref),0.0f);     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(x[0]), (int)(y[0]),"y",Label.LEFT,TOP, axis1);
            
            // Force in the front
            if((Current1 > 0 && Current2 < 0) || (Current1 < 0 && Current2 > 0)){
                draw3DVector(g, 50, 30, 0.0, ywireA+1.2, zforce, 0.0, ywireA+5, zforce, 4, Forceout);
                projection = projector.project(0.0f,(float)(ywireA+4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","2",Label.LEFT,TOP, Forceout);
            }
            else if((Current1 > 0 && Current2 > 0) || (Current1 < 0 && Current2 < 0)){
                draw3DVector(g, 50, 30, 0.0, ywireA+5, zforce, 0.0, ywireA+1.2, zforce, 4, Forcein);
                projection = projector.project(0.0f,(float)(ywireA+4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","2",Label.LEFT,TOP, Forcein);
            }
            
      }
      else{
          
            draw3DVector(g, axisL, 20, 0.0, ywireA+1, 0.0, 0.0, axis_ref, 0.0, thick1, axis1); // y-axis
            projection = projector.project(0.0f,(float)(axis_ref),0.0f);     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(x[0]), (int)(y[0]),"y",Label.LEFT,TOP, axis1);
            
            if((Current1 > 0 && Current2 < 0) || (Current1 < 0 && Current2 > 0)){
                draw3DVector(g, 50, 30, 0.0, ywireA+1.2, zforce, 0.0, ywireA+5, zforce, 4, Forceout);
                projection = projector.project(0.0f,(float)(ywireA+4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","2",Label.LEFT,TOP, Forceout);
            }
            else if((Current1 > 0 && Current2 > 0) || (Current1 < 0 && Current2 < 0)){
                draw3DVector(g, 50, 30, 0.0, ywireA+5, zforce, 0.0, ywireA+1.2, zforce, 4, Forcein);
                projection = projector.project(0.0f,(float)(ywireA+4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","2",Label.LEFT,TOP, Forcein);
            }
            
            g2d.setComposite(AlphaComposite.getInstance(rule, 0.9f));
            draw3DVector(g, 0, 20, 0.0, ywireA, -wireLen, 0.0, ywireA, wireLen, thickwire, wire2);
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
            
            if(enter_E){
                if(Current1 > 0){
                    draw3DVector(g, 50, 30, 4.0, ywireA-1.5, 0.0, -4.0, ywireA-1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireA+B1shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 1",Label.LEFT,TOP, Bcolor);
                }
                else if(Current1 < 0){
                    draw3DVector(g, 50, 30, -4.0, ywireA-1.5, 0.0, 4.0, ywireA-1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireA+B1shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 1",Label.LEFT,TOP, Bcolor);
                }
            }
            if(Current2 > 0){
                draw3DVector(g, 50, 30, 0.0, ywireA, wireLen-2.8, 0.0, ywireA, wireLen+0.8, 5, arrow2);
            }
            else if(Current2 < 0){
                draw3DVector(g, 50, 30, 0.0, ywireA, wireLen+0.8, 0.0, ywireA, wireLen-2.8, 5, arrow2);
            }
            
            draw3DVector(g, axisL, 20, 0.0, 0.0, 0.0, axis_ref, 0.0, 0.0, thick1, axis1); // x-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, -axis_ref, 0.0, 0.0, thick1, 5, axis1); // x-axis
            projection = projector.project((float)(axis_ref),0.0f,0.0f);     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(x[0]), (int)(y[0]),"x",Label.LEFT,TOP, axis1);
            
            draw3DVector(g, 0, 20, 0.0, 0.0, 0.0, 0.0, ywireA-1, 0.0, thick1, axis1); // y-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, 0.0, ywireB+1, 0.0, thick1, 5, axis1); // y-axis
            
            draw3DVector(g, axisL, 20, 0.0, 0.0, 0.0, 0.0, 0.0, axis_ref, thick1, axis1); // z-axis
            draw3DVectorDash(g, 0, 20, 0.0, 0.0, 0.0, 0.0, 0.0, -axis_ref, thick1, 5, axis1); // z-axis
            projection = projector.project(0.0f,0.0f,(float)(axis_ref));     
            x[0] = projection.x; y[0] = projection.y;
            outString(g,(int)(1.03*x[0]), (int)(y[0]),"z",Label.LEFT,CENTER, axis1);
            
            if(!enter_E){
                if(Current2 > 0){
                    draw3DVector(g, 50, 30, -4.0, ywireB+1.5, 0.0, 4.0, ywireB+1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireB+B2shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 2",Label.LEFT,TOP, Bcolor);
                }
                else if(Current2 < 0){
                    draw3DVector(g, 50, 30, 4.0, ywireB+1.5, 0.0, -4.0, ywireB+1.5, 0.0, 5, Bcolor);
                    projection = projector.project(0.0f,(float)(ywireB+B2shift),(float)(-1.0));     
                        x[0] = projection.x; y[0] = projection.y;
                        outString3(g,(int)(x[0]), (int)(y[0]),"B"," 2",Label.LEFT,TOP, Bcolor);
                }
            }
            g2d.setComposite(AlphaComposite.getInstance(rule, 0.9f));
            draw3DVector(g, 0, 20, 0.0, ywireB, -wireLen, 0.0, ywireB, wireLen, thickwire, wire1);
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
            
            if(Current1 > 0){
                draw3DVector(g, 50, 30, 0.0, ywireB, wireLen-2.8, 0.0, ywireB, wireLen+0.8, 5, arrow1);
            }
            else if(Current1 < 0){
                draw3DVector(g, 50, 30, 0.0, ywireB, wireLen+0.8, 0.0, ywireB, wireLen-2.8, 5, arrow1);
            } 
            
            draw3DVectorDash(g, 0, 20, 0.0, ywireB-1, 0.0, 0.0, -axis_ref, 0.0, thick1, 5, axis1); // y-axis
            
            if((Current1 > 0 && Current2 < 0) || (Current1 < 0 && Current2 > 0)){
                draw3DVector(g, 50, 30, 0.0, ywireB-1.2, zforce, 0.0, ywireB-5, zforce, 4, Forceout);
                projection = projector.project(0.0f,(float)(ywireB-4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","1",Label.LEFT,TOP, Forceout);
            }
            else if((Current1 > 0 && Current2 > 0) || (Current1 < 0 && Current2 < 0)){
                draw3DVector(g, 50, 30, 0.0, ywireB-5, zforce, 0.0, ywireB-1.2, zforce, 4, Forcein);
                projection = projector.project(0.0f,(float)(ywireB-4),(float)(4.0+zforce));     
                    x[0] = projection.x; y[0] = projection.y;
                    outString3(g,(int)(x[0]), (int)(y[0]),"F","1",Label.LEFT,TOP, Forcein);
            }
      }
      //g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
      
      if((Current1 > 0 && Current2 < 0) || (Current1 < 0 && Current2 > 0)){
                g.setColor(Color.red.darker());
                MaestroG.subsupspecial("Wires repel each other with equal force","","","","",g, 18, 25, getSize().height - 25);
      }
      else if((Current1 > 0 && Current2 > 0) || (Current1 < 0 && Current2 < 0)){
                g.setColor(Color.blue.darker());
                MaestroG.subsupspecial("Wires attract each other with equal force","","","","",g, 18, 25, getSize().height - 25);
      }
      else{             
                g.setColor(Color.black);
                MaestroG.subsupspecial("No force between wires","","","","",g, 18, 25, getSize().height - 25);
      }
      
      //g2d.setComposite(AlphaComposite.getInstance(rule, 0.3f));
      // second half
      
      //if(enter_E){draw3DCircleThickZ1(g, 0.0, ywireB, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      //else{draw3DCircleThickZ1(g, 0.0, ywireA, 0.0, ywireA*2.0-1.2, 5, ColorHH);}
      //g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
       
  }
  
  //----------------------------------------------------------------------------
  
  private void FillArcTransp(Graphics g, double xCenter, double yCenter, double Radius, double startangle, double endangle, Color color, double alphachan){
	int rule; float alpha;
        rule = AlphaComposite.SRC_OVER;
        alpha = (float)alphachan;
        
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
        
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        Arc2D.Double arc_one = new Arc2D.Double(xCenter-Radius,yCenter-Radius,Radius*2.0,Radius*2.0,startangle,endangle,2);
        g2d.fill(arc_one);
  
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
        
}
  
  //----------------------------------------------------------------------------
  
  private final void outString(Graphics g, int x, int y, String s, int x_align, int y_align, Color colore) {
      Font LabelFont = new Font("Serif",Font.BOLD | Font.ITALIC,22);
      g.setFont(LabelFont);
      g.setColor(colore);
    switch (y_align) {
      case TOP    : y += g.getFontMetrics(g.getFont()).getAscent(); break;
      case CENTER : y += g.getFontMetrics(g.getFont()).getAscent()/2; break;
    }
    switch (x_align) {
      case Label.LEFT  : g.drawString(s,x,y); 
                         break;
      case Label.RIGHT : g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s),y); 
                         break;
      case Label.CENTER: g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s)/2,y); 
                         break;
    }     
  }
  
  private final void outString2(Graphics g, int x, int y, String s, int x_align, int y_align, Color colore) {
      Font LabelFont = new Font("Serif",Font.BOLD,18);
      g.setFont(LabelFont);
      g.setColor(colore);
    switch (y_align) {
      case TOP    : y += g.getFontMetrics(g.getFont()).getAscent(); break;
      case CENTER : y += g.getFontMetrics(g.getFont()).getAscent()/2; break;
    }
    switch (x_align) {
      case Label.LEFT  : g.drawString(s,x,y); 
                         break;
      case Label.RIGHT : g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s),y); 
                         break;
      case Label.CENTER: g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s)/2,y); 
                         break;
    }     
  }
  
  private final void outString3(Graphics g, int x, int y, String s, String s2, int x_align, int y_align, Color colore) {
      Font LabelFont = new Font("Serif",Font.BOLD,25);
      Font LabelFont2 = new Font("Serif",Font.BOLD,20);
      g.setFont(LabelFont);
      g.setColor(colore);
    switch (y_align) {
      case TOP    : y += g.getFontMetrics(g.getFont()).getAscent(); break;
      case CENTER : y += g.getFontMetrics(g.getFont()).getAscent()/2; break;
    }
    switch (x_align) {
      case Label.LEFT  : g.setFont(LabelFont);g.drawString(s,x,y); g.setFont(LabelFont2);g.drawString(s2,x+12,y+8); 
                         break;
      case Label.RIGHT : g.setFont(LabelFont);g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s),y); 
                         g.setFont(LabelFont2);g.drawString(s2,x-g.getFontMetrics(g.getFont()).stringWidth(s)+12,y+8); 
                         break;
      case Label.CENTER: g.setFont(LabelFont);g.drawString(s,x-g.getFontMetrics(g.getFont()).stringWidth(s)/2,y); 
                         g.setFont(LabelFont2);g.drawString(s2,x-g.getFontMetrics(g.getFont()).stringWidth(s)/2+12,y+8); 
                         break;
    }     
  }
  
  private void draw3DVector(Graphics g, float axisL, int tip_ratio, double vx1, double vy1, double vz1, double vx2, double vy2, double vz2, int thick, Color colore){
          
          Point projection;
          double vtipx, vtipy;
          double vposx, vposy;
          //length of arrow head lines
          double varrow = axisL/(float)tip_ratio;   
      
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

          //Get projection on 2D plane for origin of vector
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx = (double)projection.x;
          vposy = (double)projection.y;

          //Get projection on 2D plane for tip of vector
          projection = projector.project((float)vx2, (float)vy2, (float)vz2);
          vtipx = (double)projection.x;
          vtipy = (double)projection.y;

          //draw vector in 2D
          //g.drawLine(x[0],y[0],projection.x,projection.y); // OLD GRAPHICS
          
          
          drawLineThick(g, vposx, vposy, vtipx, vtipy, thick, colore); // JAVA 2D GRAPHICS - needs double values
          
            //-----------------------------------------------------------------------
            //drawing of arrow head at tip of vector
            
            double dvec, xsq, ysq, zsq, gamma_angle, Dz1, Dz2, Dx1, Dx2, Dy1, Dy2, 
                   theta, DL1, DL2, D1, D2, ref_angle, ref_angle2;
            double cox, coy, coz;

            theta = Math.PI/12.0;
            
            xsq = Math.pow(vx2-vx1,2);
            ysq = Math.pow(vy2-vy1,2);
            zsq = Math.pow(vz2-vz1,2);

            dvec = Math.sqrt(xsq + ysq + zsq);

            //direction cosines
            cox = (vx2 - vx1)/dvec;
            coy = (vy2 - vy1)/dvec;
            coz = (vz2 - vz1)/dvec;

            gamma_angle = Math.acos(coz);

            ref_angle = 0.5*Math.PI - gamma_angle - theta;
            ref_angle2 = gamma_angle - theta;

            Dz1 = vz2 - varrow * Math.sin(ref_angle);
            DL1 = varrow * Math.cos(ref_angle);
            //D1 = dvec * Math.sin(gamma_angle);

            Dz2 = vz2 - varrow * Math.cos(ref_angle2);
            DL2 = varrow * Math.sin(ref_angle2);
            //D2 = dvec * Math.sin(gamma_angle);
            if(gamma_angle > 0.0 && gamma_angle < Math.PI){
                Dx1 = vx2 - DL1 * cox/Math.sin(gamma_angle);
                Dy1 = vy2 - DL1 * coy/Math.sin(gamma_angle);
                Dx2 = vx2 - DL2 * cox/Math.sin(gamma_angle);
                Dy2 = vy2 - DL2 * coy/Math.sin(gamma_angle);
            }
            else{//When polar angle --> zero, ratios cox/Math.sin() gives NaN
                 //Set limit of ratio to one.
                Dx1 = vx2 + DL1;
                Dy1 = vy2 - DL1;
                Dx2 = vx2 + DL2;
                Dy2 = vy2 - DL2;
            }
            //Get projection on 2D plane for origin of vector
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx1, (float)Dy1, (float)Dz1);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw first line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values

            //Get projection on 2D plane for origin of line
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx2, (float)Dy2, (float)Dz2);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw second line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values
            
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  }
  
  private void draw3DVectorDouble(Graphics g, float axisL, int tip_ratio, double vx1, double vy1, double vz1, double vx2, double vy2, double vz2, int thick, Color colore){
          
          Point projection;
          double vtipx, vtipy;
          double vposx, vposy;
          //length of arrow head lines
          double varrow = axisL/(float)tip_ratio;   
      
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

          //Get projection on 2D plane for origin of vector
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx = (double)projection.x;
          vposy = (double)projection.y;

          //Get projection on 2D plane for tip of vector
          projection = projector.project((float)vx2, (float)vy2, (float)vz2);
          vtipx = (double)projection.x;
          vtipy = (double)projection.y;

          //draw vector in 2D
          //g.drawLine(x[0],y[0],projection.x,projection.y); // OLD GRAPHICS
          
          
          drawLineThick(g, vposx, vposy, vtipx, vtipy, thick, colore); // JAVA 2D GRAPHICS - needs double values
          
            //-----------------------------------------------------------------------
            //drawing of arrow head at tip of vector
            
            double dvec, xsq, ysq, zsq, gamma_angle, Dz1, Dz2, Dx1, Dx2, Dy1, Dy2, 
                   theta, DL1, DL2, D1, D2, ref_angle, ref_angle2;
            double cox, coy, coz;

            theta = Math.PI/12.0;
            
            xsq = Math.pow(vx2-vx1,2);
            ysq = Math.pow(vy2-vy1,2);
            zsq = Math.pow(vz2-vz1,2);

            dvec = Math.sqrt(xsq + ysq + zsq);

            //direction cosines
            cox = (vx2 - vx1)/dvec;
            coy = (vy2 - vy1)/dvec;
            coz = (vz2 - vz1)/dvec;

            gamma_angle = Math.acos(coz);

            ref_angle = 0.5*Math.PI - gamma_angle - theta;
            ref_angle2 = gamma_angle - theta;

            Dz1 = vz2 - varrow * Math.sin(ref_angle);
            DL1 = varrow * Math.cos(ref_angle);
            //D1 = dvec * Math.sin(gamma_angle);

            Dz2 = vz2 - varrow * Math.cos(ref_angle2);
            DL2 = varrow * Math.sin(ref_angle2);
            //D2 = dvec * Math.sin(gamma_angle);
            if(gamma_angle > 0.0 && gamma_angle < Math.PI){
                Dx1 = vx2 + DL1 * cox/Math.sin(gamma_angle);
                Dy1 = vy2 + DL1 * coy/Math.sin(gamma_angle);
                Dx2 = vx2 + DL2 * cox/Math.sin(gamma_angle);
                Dy2 = vy2 + DL2 * coy/Math.sin(gamma_angle);
            }
            else{//When polar angle --> zero, ratios cox/Math.sin() gives NaN
                 //Set limit of ratio to one.
                Dx1 = vx2 - DL1;
                Dy1 = vy2 + DL1;
                Dx2 = vx2 - DL2;
                Dy2 = vy2 + DL2;
            }
            //Get projection on 2D plane for origin of vector
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx1, (float)Dy1, (float)Dz1);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw first line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values

            //Get projection on 2D plane for origin of line
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx2, (float)Dy2, (float)Dz2);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw second line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values
            
            //----------------------------------------------------------------------     
            //-----------------------------------------------------------------------
            //drawing of arrow head at other end of vector
            
            //double dvec, xsq, ysq, zsq, gamma_angle, Dz1, Dz2, Dx1, Dx2, Dy1, Dy2, 
              //     theta, DL1, DL2, D1, D2, ref_angle, ref_angle2;
            //double cox, coy, coz;

            theta = Math.PI/12.0;
            
            xsq = Math.pow(vx2-vx1,2);
            ysq = Math.pow(vy2-vy1,2);
            zsq = Math.pow(vz2-vz1,2);

            dvec = Math.sqrt(xsq + ysq + zsq);

            //direction cosines
            cox = (vx2 - vx1)/dvec;
            coy = (vy2 - vy1)/dvec;
            coz = (vz2 - vz1)/dvec;

            gamma_angle = Math.acos(coz);

            ref_angle = 0.5*Math.PI - gamma_angle - theta;
            ref_angle2 = gamma_angle - theta;

            Dz1 = vz1 - varrow * Math.sin(ref_angle);
            DL1 = varrow * Math.cos(ref_angle);
            //D1 = dvec * Math.sin(gamma_angle);

            Dz2 = vz1 - varrow * Math.cos(ref_angle2);
            DL2 = varrow * Math.sin(ref_angle2);
            //D2 = dvec * Math.sin(gamma_angle);
            if(gamma_angle > 0.0 && gamma_angle < Math.PI){
                Dx1 = vx1 - DL1 * cox/Math.sin(gamma_angle);
                Dy1 = vy1 - DL1 * coy/Math.sin(gamma_angle);
                Dx2 = vx1 - DL2 * cox/Math.sin(gamma_angle);
                Dy2 = vy1 - DL2 * coy/Math.sin(gamma_angle);
            }
            else{//When polar angle --> zero, ratios cox/Math.sin() gives NaN
                 //Set limit of ratio to one.
                Dx1 = vx1 + DL1;
                Dy1 = vy1 - DL1;
                Dx2 = vx1 + DL2;
                Dy2 = vy1 - DL2;
            }
            //Get projection on 2D plane for origin of vector
            projection = projector.project((float)vx1, (float)vy1, (float)vz1);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx1, (float)Dy1, (float)Dz1);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw first line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values

            //Get projection on 2D plane for origin of line
            projection = projector.project((float)vx1, (float)vy1, (float)vz1);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx2, (float)Dy2, (float)Dz2);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw second line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values
            
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  }
  
  private void draw3DVectorDash(Graphics g, float axisL, int tip_ratio, double vx1, double vy1, double vz1, double vx2, double vy2, double vz2, int thick, int dash, Color colore){
          
          Point projection;
          double vtipx, vtipy;
          double vposx, vposy;
          //length of arrow head lines
          double varrow = axisL/(float)tip_ratio;   
      
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

          //Get projection on 2D plane for origin of vector
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx = (double)projection.x;
          vposy = (double)projection.y;

          //Get projection on 2D plane for tip of vector
          projection = projector.project((float)vx2, (float)vy2, (float)vz2);
          vtipx = (double)projection.x;
          vtipy = (double)projection.y;

          //draw vector in 2D
          //g.drawLine(x[0],y[0],projection.x,projection.y); // OLD GRAPHICS
          
          //stem of vector Graphics g, double x1, double y1, double x2, double y2, int thick, int dash, Color color
          drawDashLineThick(g, vposx, vposy, vtipx, vtipy, thick, dash,colore); // JAVA 2D GRAPHICS - needs double values
          
            //-----------------------------------------------------------------------
            //drawing of arrow head at tip of vector
            
            double dvec, xsq, ysq, zsq, gamma_angle, Dz1, Dz2, Dx1, Dx2, Dy1, Dy2, 
                   theta, DL1, DL2, D1, D2, ref_angle, ref_angle2;
            double cox, coy, coz;

            theta = Math.PI/12.0;
            
            xsq = Math.pow(vx2-vx1,2);
            ysq = Math.pow(vy2-vy1,2);
            zsq = Math.pow(vz2-vz1,2);

            dvec = Math.sqrt(xsq + ysq + zsq);

            //direction cosines
            cox = (vx2 - vx1)/dvec;
            coy = (vy2 - vy1)/dvec;
            coz = (vz2 - vz1)/dvec;

            gamma_angle = Math.acos(coz);

            ref_angle = 0.5*Math.PI - gamma_angle - theta;
            ref_angle2 = gamma_angle - theta;

            Dz1 = vz2 - varrow * Math.sin(ref_angle);
            DL1 = varrow * Math.cos(ref_angle);
            //D1 = dvec * Math.sin(gamma_angle);

            Dz2 = vz2 - varrow * Math.cos(ref_angle2);
            DL2 = varrow * Math.sin(ref_angle2);
            //D2 = dvec * Math.sin(gamma_angle);
            if(gamma_angle > 0.0 && gamma_angle < Math.PI){
                Dx1 = vx2 - DL1 * cox/Math.sin(gamma_angle);
                Dy1 = vy2 - DL1 * coy/Math.sin(gamma_angle);
                Dx2 = vx2 - DL2 * cox/Math.sin(gamma_angle);
                Dy2 = vy2 - DL2 * coy/Math.sin(gamma_angle);
            }
            else{//When polar angle --> zero, ratios cox/Math.sin() gives NaN
                 //Set limit of ratio to one.
                Dx1 = vx2 + DL1;
                Dy1 = vy2 - DL1;
                Dx2 = vx2 + DL2;
                Dy2 = vy2 - DL2;
            }
            //Get projection on 2D plane for origin of vector
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx1, (float)Dy1, (float)Dz1);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw first line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values

            //Get projection on 2D plane for origin of line
            projection = projector.project((float)vx2, (float)vy2, (float)vz2);
            vposx = (double)projection.x;
            vposy = (double)projection.y;

            //Get projection on 2D plane for tip of vector
            projection = projector.project((float)Dx2, (float)Dy2, (float)Dz2);
            vtipx = (double)projection.x;
            vtipy = (double)projection.y;

            //draw second line of arrow head 
            drawLineThick(g, vposx, vposy, vtipx, vtipy, thick+1, colore); // JAVA 2D GRAPHICS - needs double values
            
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  }
  
  private void draw3DLine(Graphics g, double vx1, double vy1, double vz1, double vx2, double vy2, double vz2, int thick, Color colore){
          
          Point projection;
          double vtipx, vtipy;
          double vposx, vposy;
          
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          //g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

          //Get projection on 2D plane for origin of vector
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx = (double)projection.x;
          vposy = (double)projection.y;

          //Get projection on 2D plane for tip of vector
          projection = projector.project((float)vx2, (float)vy2, (float)vz2);
          vtipx = (double)projection.x;
          vtipy = (double)projection.y;

          //draw vector in 2D
          //g.drawLine(x[0],y[0],projection.x,projection.y); // OLD GRAPHICS
          
          drawDashLineThick(g, vposx, vposy, vtipx, vtipy, thick, 5, colore); // JAVA 2D GRAPHICS - needs double values
          //System.out.println("vposy = "+vposy+"   vtipy = "+vtipy);
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  }
  
   private void draw3DParallelepipedon(Graphics g, double vx1, double vy1, double vz1, 
                                                   double vx2, double vy2, double vz2, 
                                                   double vx3, double vy3, double vz3,
                                                   double vx4, double vy4, double vz4,
                                                   double vx5, double vy5, double vz5,
                                                   double vx6, double vy6, double vz6,
                                                   double vx7, double vy7, double vz7,
                                                   double vx8, double vy8, double vz8,
                                                   int thick, Color colore, 
                                                   Color colorbottom, 
                                                   Color colorside1, 
                                                   Color colorside2){
          
          //This routine contructs a 6 face parallelepipedon.
          //User must make sure that the points are coplanare in 
          //groups four to give a proper solid figure.
          //To obtain a cube, all faces should have identical areas
                                                       
          Point projection;
          double vposx1, vposy1, vposx2, vposy2, vposx3, vposy3, vposx4, vposy4;
          double vposx5, vposy5, vposx6, vposy6, vposx7, vposy7, vposx8, vposy8;
          
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
          
          //Get projection on 2D plane for nodes
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx1 = (double)projection.x;
          vposy1 = (double)projection.y;
          
          projection = projector.project((float)vx2,(float)vy2,(float)vz2);
          vposx2 = (double)projection.x;
          vposy2 = (double)projection.y;
          
          projection = projector.project((float)vx3,(float)vy3,(float)vz3);
          vposx3 = (double)projection.x;
          vposy3 = (double)projection.y;
          
          projection = projector.project((float)vx4,(float)vy4,(float)vz4);
          vposx4 = (double)projection.x;
          vposy4 = (double)projection.y;
          
          projection = projector.project((float)vx5,(float)vy5,(float)vz5);
          vposx5 = (double)projection.x;
          vposy5 = (double)projection.y;
           
          projection = projector.project((float)vx6,(float)vy6,(float)vz6);
          vposx6 = (double)projection.x;
          vposy6 = (double)projection.y;
          
          projection = projector.project((float)vx7,(float)vy7,(float)vz7);
          vposx7 = (double)projection.x;
          vposy7 = (double)projection.y;
          
          // draw sides of cube - Could be done with polygns instead of lines
          projection = projector.project((float)vx8,(float)vy8,(float)vz8);
          vposx8 = (double)projection.x;
          vposy8 = (double)projection.y;
          
          drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick, colore); 
          drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick, colore); 
          drawLineThick(g, vposx2, vposy2, vposx4, vposy4, thick, colore);
          drawLineThick(g, vposx3, vposy3, vposx4, vposy4, thick, colore); 
          
          drawLineThick(g, vposx5, vposy5, vposx6, vposy6, thick, colore); 
          drawLineThick(g, vposx5, vposy5, vposx7, vposy7, thick, colore); 
          drawLineThick(g, vposx6, vposy6, vposx8, vposy8, thick, colore);
          drawLineThick(g, vposx7, vposy7, vposx8, vposy8, thick, colore); 
          
          drawLineThick(g, vposx1, vposy1, vposx5, vposy5, thick, colore); 
          drawLineThick(g, vposx3, vposy3, vposx7, vposy7, thick, colore); 
          drawLineThick(g, vposx2, vposy2, vposx6, vposy6, thick, colore);
          drawLineThick(g, vposx4, vposy4, vposx8, vposy8, thick, colore); 
          
          //Draw faces
          // transparency parameters
          int rule; 
          float alpha;
          rule = AlphaComposite.SRC_OVER;
            
          int xpoly[] = new int[4];
          int ypoly[] = new int[4];
          
          alpha = 0.3f;
          
          g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
	  
          // Make faces with Polygons
          
          //bottom face
          xpoly[0] = (int)vposx3; xpoly[1] = (int)vposx4;
          xpoly[2] = (int)vposx8; xpoly[3] = (int)vposx7;
          ypoly[0] = (int)vposy3; ypoly[1] = (int)vposy4;
          ypoly[2] = (int)vposy8; ypoly[3] = (int)vposy7;
          
          //g.setColor(colorbottom);
          //g.fillPolygon(xpoly,ypoly,4); // regular Java Graphics
          
          g2d.setPaint(colorbottom);// Java 2D implementation
          GeneralPath s = new GeneralPath();
          s.moveTo((float)xpoly[0], (float)ypoly[0]);
          s.lineTo((float)xpoly[1], (float)ypoly[1]);
          s.lineTo((float)xpoly[2], (float)ypoly[2]);
          s.lineTo((float)xpoly[3], (float)ypoly[3]);
          s.closePath();
          g2d.fill(s);
          
          // outline of faces using polygons instead of lines
          // Note change in transparency
          //alpha = 0.3f;
          //g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
          //g2d.setPaint(colore);
          //g2d.draw(s);
          //alpha = 0.1f;
          //g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
	  
          // side face 1
          xpoly[0] = (int)vposx1; xpoly[1] = (int)vposx5;
          xpoly[2] = (int)vposx7; xpoly[3] = (int)vposx3;
          ypoly[0] = (int)vposy1; ypoly[1] = (int)vposy5;
          ypoly[2] = (int)vposy7; ypoly[3] = (int)vposy3;
          
          //g.setColor(colorside1);
          //g.fillPolygon(xpoly,ypoly,4); // regular Java Graphics
	  
          g2d.setPaint(colorside1);// Java 2D implementation
          GeneralPath s2 = new GeneralPath();
          s2.moveTo((float)xpoly[0], (float)ypoly[0]);
          s2.lineTo((float)xpoly[1], (float)ypoly[1]);
          s2.lineTo((float)xpoly[2], (float)ypoly[2]);
          s2.lineTo((float)xpoly[3], (float)ypoly[3]);
          s2.closePath();
          g2d.fill(s2);
          
          // side face 2
          xpoly[0] = (int)vposx5; xpoly[1] = (int)vposx6;
          xpoly[2] = (int)vposx8; xpoly[3] = (int)vposx7;
          ypoly[0] = (int)vposy5; ypoly[1] = (int)vposy6;
          ypoly[2] = (int)vposy8; ypoly[3] = (int)vposy7;
          
          //g.setColor(colorside2);
          //g.fillPolygon(xpoly,ypoly,4); // regular Java Graphics
          
          g2d.setPaint(colorside2);// Java 2D implementation
          GeneralPath s3 = new GeneralPath();
          s3.moveTo((float)xpoly[0], (float)ypoly[0]);
          s3.lineTo((float)xpoly[1], (float)ypoly[1]);
          s3.lineTo((float)xpoly[2], (float)ypoly[2]);
          s3.lineTo((float)xpoly[3], (float)ypoly[3]);
          s3.closePath();
          g2d.fill(s3);
          
          g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f)); 
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  }
   
  private void FillPatch(Graphics g, double vxpatch1, double vypatch1,
                                     double vxpatch2, double vypatch2,
                                     double vxpatch3, double vypatch3,
                                     double vxpatch4, double vypatch4,
                                     float transp, Color colore){
          
          //This routine fills a 4-point patch with two triangles.
                                                       
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
          
          //Draw faces
          // transparency parameters
          int rule; 
          float alpha;
          rule = AlphaComposite.SRC_OVER;
            
          int xpoly[] = new int[4];
          int ypoly[] = new int[4];
          
          alpha = transp; //0.3f;
          g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
	  
          // Make patch with two triangles
          
          //lower triangle
          xpoly[0] = (int)vxpatch1; xpoly[1] = (int)vxpatch2;
          xpoly[2] = (int)vxpatch3; 
          ypoly[0] = (int)vypatch1; ypoly[1] = (int)vypatch2;
          ypoly[2] = (int)vypatch3; 
          
          GeneralPath s = new GeneralPath();
          s.moveTo((float)xpoly[0], (float)ypoly[0]);
          s.lineTo((float)xpoly[1], (float)ypoly[1]);
          s.lineTo((float)xpoly[2], (float)ypoly[2]);
          s.closePath();
          g2d.fill(s);
          
          xpoly[0] = (int)vxpatch2; xpoly[1] = (int)vxpatch3;
          xpoly[2] = (int)vxpatch4; 
          ypoly[0] = (int)vypatch2; ypoly[1] = (int)vypatch3;
          ypoly[2] = (int)vypatch4; 
          
          GeneralPath s2 = new GeneralPath();
          s2.moveTo((float)xpoly[0], (float)ypoly[0]);
          s2.lineTo((float)xpoly[1], (float)ypoly[1]);
          s2.lineTo((float)xpoly[2], (float)ypoly[2]);
          s2.closePath();
          g2d.fill(s2);
          
          
          g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f)); 
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  } 
   
  private void drawTriangle(Graphics g, double vx1, double vy1, double vz1, 
                                                   double vx2, double vy2, double vz2, 
                                                   double vx3, double vy3, double vz3,
                                                   int thick, Color colore){
          
          //This routine contructs a 6 face parallelepipedon.
          //User must make sure that the points are coplanare in 
          //groups four to give a proper solid figure.
          //To obtain a cube, all faces should have identical areas
                                                       
          Point projection;
          double vposx1, vposy1, vposx2, vposy2, vposx3, vposy3;
          
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
          
          //Get projection on 2D plane for nodes
          projection = projector.project((float)vx1,(float)vy1,(float)vz1);
          vposx1 = (double)projection.x;
          vposy1 = (double)projection.y;
          
          projection = projector.project((float)vx2,(float)vy2,(float)vz2);
          vposx2 = (double)projection.x;
          vposy2 = (double)projection.y;
          
          projection = projector.project((float)vx3,(float)vy3,(float)vz3);
          vposx3 = (double)projection.x;
          vposy3 = (double)projection.y;
          
          
          drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick, colore); 
          drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick, colore); 
          drawLineThick(g, vposx2, vposy2, vposx3, vposy3, thick, colore);
          //----------------------------------------------------------------------     
          //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
  } 
  
  private void drawDashLineThick(Graphics g, double x1, double y1, double x2, double y2, int thick, int dash, Color color){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
        float[] dashPattern = {dash,dash};
        g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,10.0F,dashPattern,0));  
        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.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
        
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
  
  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);
    }
  
  private void drawLineThick2(Graphics g, double x1, double y1, double x2, double y2, int thick, Color color){
        // Some routine as above, but no smoothing
        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_OFF);
        
        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);
    }
  
    private void drawCircleHorizontalThick(Graphics g, double xCenter, double yCenter, double zCenter, double Radius, int thick, Color color){	
          Point projection;
          double vposx, vposy, rado, centro;
          
          Graphics2D g2d = (Graphics2D)g;
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
          
          //Get projection on 2D plane for nodes
          projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
          vposx = (double)projection.x;
          vposy = (double)projection.y;
          
          //Get length of radius
          rado = (double)projector.getLong(Radius);
        
        
        //g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        float[] dashPattern = {5,5};
        g2d.setStroke(new BasicStroke(1,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER,10.0F,dashPattern,0)); 
        g2d.setPaint(Color.lightGray);
        Ellipse2D.Double circle1 = new Ellipse2D.Double(vposx-rado,vposy-rado*Math.sin(Math.PI/180.0*projector.getElevationAngle()),2*rado,(2*rado)*Math.sin(Math.PI/180.0*projector.getElevationAngle()));
        g2d.draw(circle1);
        
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        g2d.setPaint(color);
        int rule; 
        float alpha;
        rule = AlphaComposite.SRC_OVER;
        g2d.setComposite(AlphaComposite.getInstance(rule, 0.1f));
        Ellipse2D.Double circle = new Ellipse2D.Double(vposx-rado,vposy-rado*Math.sin(Math.PI/180.0*projector.getElevationAngle()),2*rado,(2*rado)*Math.sin(Math.PI/180.0*projector.getElevationAngle()));
        g2d.draw(circle);
        g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
        g2d.setStroke(new BasicStroke(1));
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }

    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 fillCircleThick(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);
    }
    
    // WORK IN PROGRESS
    private void draw3DCircleThick(Graphics g, double xCenter, double yCenter, 
                                   double zCenter, double Radius, 
                                   double anglex, double angley, double anglez, 
                                   int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
          
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        Ellipse2D.Double circle = new Ellipse2D.Double(xProjCenter-Radius,yProjCenter-Radius,2*Radius,2*Radius);
        g2d.draw(circle);
        g2d.setStroke(new BasicStroke(1));
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void draw3DCircleThickX1(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        double xx, yy, zz, x0, y0, z0, xProj0, yProj0;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        int step = 60;
        if(Radius < 5){step = 15;}
        else if (step >= 5 && step < 8){ step = 22;}
        else if(Radius >= 8 && Radius < 15){step = 30;}
        else{step = 45;}
        
        for(int i=1; i < step+1; i++){
            x0 = xCenter; y0 = yCenter + Radius*Math.sin((i-1)*Math.PI/step); z0 = zCenter + Radius*Math.cos((i-1)*Math.PI/step);
            xx = xCenter; yy = yCenter + Radius*Math.sin(i*Math.PI/step); zz = zCenter + Radius*Math.cos(i*Math.PI/step);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            projection = projector.project((float)x0,(float)y0,(float)z0);
            xProj0 = (double)projection.x;
            yProj0 = (double)projection.y;
            
        
            //drawLineThick(g, xProj0, yProj0, xProjCenter, yProjCenter, thick, color); // make dots
            drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color); // make dots
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void draw3DCircleThickX2(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        double xx, yy, zz, x0, y0, z0, xProj0, yProj0;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        int step = 30;
        if(Radius < 5){step = 15;}
        else if (step >= 5 && step < 8){ step = 22;}
        else if(Radius >= 8 && Radius < 15){step = 30;}
        else{step = 45;}
        
        for(int i=0; i < (step+1); i++){
            x0 = xCenter; y0 = yCenter + Radius*Math.sin((i-1)*Math.PI/step+Math.PI); z0 = zCenter + Radius*Math.cos((i-1)*Math.PI/step+Math.PI);
            xx = xCenter; yy = yCenter + Radius*Math.sin(i*Math.PI/step+Math.PI); zz = zCenter + Radius*Math.cos(i*Math.PI/step+Math.PI);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            projection = projector.project((float)x0,(float)y0,(float)z0);
            xProj0 = (double)projection.x;
            yProj0 = (double)projection.y;
            
            //drawLineThick(g, xProj0, yProj0, xProjCenter, yProjCenter, thick, color); // make dots
            drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void draw3DCircleThickZ1(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        double xx, yy, zz, x0, y0, z0, xProj0, yProj0;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        int step = 120 * (int)(Radius)/10;
        //if(Radius < 5){step = 30;}
        //else if (step >= 5 && step < 8){ step = 45;}
        //else if(Radius >= 8 && Radius < 15){step = 60;}
        //else{step = 90;}
        double plus = projector.getAzimuthAngle() *Math.PI/180.0;
        
        for(int i=1; i < step+1; i++){
            z0 = zCenter; y0 = yCenter + Radius*Math.sin(((i-1)*Math.PI)/step-plus); 
            x0 = xCenter + Radius*Math.cos(((i-1)*Math.PI)/step-plus);
            zz = zCenter; yy = yCenter + Radius*Math.sin((i*Math.PI)/step-plus); 
            xx = xCenter + Radius*Math.cos((i*Math.PI)/step-plus);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            projection = projector.project((float)x0,(float)y0,(float)z0);
            xProj0 = (double)projection.x;
            yProj0 = (double)projection.y;
            
        
            //drawLineThick(g, xProj0, yProj0, xProjCenter, yProjCenter, thick, color); // make dots
            drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color); // make dots
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void draw3DCircleThickZ2(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        double xx, yy, zz, x0, y0, z0, xProj0, yProj0;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        double plus = projector.getAzimuthAngle() *Math.PI/180.0;
        int step = 120 * (int)(Radius)/10;
        //if(Radius < 5){step = 30;}
        //else if (step >= 5 && step < 8){ step = 45;}
        //else if(Radius >= 8 && Radius < 15){step = 60;}
        //else{step = 90;}        
        for(int i=1; i < (step+1); i++){
            z0 = zCenter; y0 = yCenter + Radius*Math.sin((i-1)*Math.PI/step+Math.PI-plus); 
            x0 = xCenter + Radius*Math.cos((i-1)*Math.PI/step+Math.PI-plus);
            zz = zCenter; yy = yCenter + Radius*Math.sin(i*Math.PI/step+Math.PI-plus); 
            xx = xCenter + Radius*Math.cos(i*Math.PI/step+Math.PI-plus);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            projection = projector.project((float)x0,(float)y0,(float)z0);
            xProj0 = (double)projection.x;
            yProj0 = (double)projection.y;
            
            //drawLineThick(g, xProj0, yProj0, xProjCenter, yProjCenter, thick, color); // make dots
            drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void drawEfield1(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        int nrad = 12;
        double xx, yy, zz;
        double xx2, yy2, zz2;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        for(int i=0; i < nrad; i++){
            xx2 = xCenter; yy2 = yCenter + 1.4*Math.sin(i*Math.PI/nrad); zz2 = zCenter + 1.4*Math.cos(i*Math.PI/nrad);
            xx = xCenter; yy = yCenter + Radius*Math.sin(i*Math.PI/nrad); zz = zCenter + Radius*Math.cos(i*Math.PI/nrad);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            draw3DVector(g, 15, 20, xx2, yy2, zz2, xx, yy, zz, thick, color);
            //drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    private void drawEfield2(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        int nrad = 12;
        double xx2, yy2, zz2;
        double xx, yy, zz;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        for(int i=0; i < nrad; i++){
            xx2 = xCenter; yy2 = yCenter + 1.4*Math.sin(i*Math.PI/nrad+Math.PI); zz2 = zCenter + 1.4*Math.cos(i*Math.PI/nrad+Math.PI);
            xx = xCenter; yy = yCenter + Radius*Math.sin(i*Math.PI/nrad+Math.PI); zz = zCenter + Radius*Math.cos(i*Math.PI/nrad+Math.PI);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            draw3DVector(g, 15, 20, xx2, yy2, zz2, xx, yy, zz, thick, color);
            //drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void drawEfield4(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        
        int nrad = 12;
        double xx2, yy2, zz2;
        double xx, yy, zz;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        for(int i=0; i < nrad; i++){
            xx2 = xCenter-5; yy2 = yCenter + 6.0*Math.sin(i*Math.PI/nrad+Math.PI); zz2 = zCenter + 6.0*Math.cos(i*Math.PI/nrad+Math.PI);
            xx = xCenter+5; yy = yCenter + Radius*Math.sin(i*Math.PI/nrad+Math.PI); zz = zCenter + Radius*Math.cos(i*Math.PI/nrad+Math.PI);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            draw3DVector(g, 15, 20, xx2, yy2, zz2, xx, yy2, zz2, thick, color);
            //drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void drawEfield3(Graphics g, double xCenter, double yCenter, double zCenter, 
                                    double Radius, int thick, Color color){
        
        Point projection;
        Graphics2D g2d = (Graphics2D)g;
        g2d.setPaint(color);
        g2d.setStroke(new BasicStroke(thick, BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL));
        
        double xProjCenter, yProjCenter;
        
        projection = projector.project((float)xCenter,(float)yCenter,(float)zCenter);
        xProjCenter = (double)projection.x;
        yProjCenter = (double)projection.y;
        int nrad = 12;
        double xx, yy, zz;
        double xx2, yy2, zz2;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        for(int i=0; i < nrad; i++){
            xx2 = xCenter-5; yy2 = yCenter + Radius*Math.sin(i*Math.PI/nrad); zz2 = zCenter + Radius*Math.cos(i*Math.PI/nrad);
            xx = xCenter+5; 
            yy = yCenter + Radius*Math.sin(i*Math.PI/nrad); zz = zCenter + Radius*Math.cos(i*Math.PI/nrad);
            projection = projector.project((float)xx,(float)yy,(float)zz);
            xProjCenter = (double)projection.x;
            yProjCenter = (double)projection.y;
            
            draw3DVector(g, 15, 20, xx2, yy2, zz2, xx, yy2, zz2, thick, color);
            //drawLineThick(g, xProjCenter, yProjCenter, xProjCenter, yProjCenter, thick, color);
        }
        
        g2d.setStroke(new BasicStroke(1));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
}
            
            //  E Field selection given k
            //------------------------------------------------------------------
            // THIS DID NOT WORK
            //if((theta_rate*Math.PI) < (Math.PI*0.5)){
              //   Ez = E_magnitude*Math.cos(phi_rateE*2.0*Math.PI) * Math.cos((theta_rate*Math.PI) + Math.PI*0.5);}
            //else{Ez = E_magnitude*Math.cos(phi_rateE*2.0*Math.PI) * Math.cos((theta_rate*Math.PI) - Math.PI*0.5);}
            //double Exy_magnitude;
            //Exy_magnitude = Math.sqrt(E_magnitude*E_magnitude - Ez*Ez);
            //Ex = Exy_magnitude * Math.cos(2.0*(phi_rate + phi_rateE)*Math.PI);
            //Ey = Exy_magnitude * Math.sin(2.0*(phi_rate + phi_rateE)*Math.PI);
            //------------------------------------------------------------------
            
/*
            //if((theta_rate*Math.PI) < (Math.PI*0.5)){
              //   Ez = E_magnitude*Math.cos(phi_rateE*2.0*Math.PI) * Math.cos((theta_rate*Math.PI) + Math.PI*0.5);}
            //else{Ez = E_magnitude*Math.cos(phi_rateE*2.0*Math.PI) * Math.cos((theta_rate*Math.PI) - Math.PI*0.5);}
            double E_intermediate;
            Ex = Math.cos(2.0*(phi_rate + phi_rateE)*Math.PI);
            Ey = Math.sin(2.0*(phi_rate + phi_rateE)*Math.PI);
            Ez = -(kx*Ex+ky*Ey)/kz;
            E_intermediate = Math.sqrt(Ex*Ex+Ey*Ey+Ez*Ez);
            */