//VectorCanvas.java
// A Canvas for drawing of a basic 3D environment

import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.JSlider;

public final class VectorCanvas extends Canvas implements Runnable, MouseListener, MouseMotionListener {
  private static Projection projector; 
  private Vector vector;
  public int xref;
  public int yref;
  
  public int latitude = 90;
  //public int longitude = 108;
  public int longitude = 164;
  //public int longitude = 216;
  
  public double exponent = 1.0;
  public double tops = 1.0;
  public boolean IsPower = false;
  public boolean ShowDipoles = true;
  //public boolean IsPatchOn = true;
  public boolean IsPatchOn = false;
  public Color color_line = Color.gray;
  public Color color_line1 = Color.gray.brighter();
  public Color color_line2 = Color.gray.brighter();
  public Color color_line3 = Color.red;
  public int number_dipoles = 5;
  
  private Image im;
  private Graphics buf;
  
  private double sfactor;
  public double distancia = .50;
  public double dipolelength = 0.50;
  public double dipolelengthA = 0.50;  // lambda
  public double dipolelengthB = 0.50;  // lambda
  public double dipolecurrentA = 1.0; // Amperes
  public double dipolecurrentB = 1.0; // Amperes
  public double scalingA = 1.0;
  public double scalingB = 1.0;
  public double fase = 180.0;
  public double R = 1.0;
  
  public double x_angle = 45.0;
  public double z_angle = 20.0;
  
  // constants           
  private static final int TOP    = 0;
  private static final int CENTER = 1;
  
  //----------------------------------------------------------------------------

  VectorCanvas(Vector vector, double sfactor) {
    super();
    this.vector = vector;
    this.sfactor = sfactor;
    projector = new Projection();
    
    //--------------------------------------------------------------------------
    // This scales the viewing distance
    // Sets "new_distance" in Projection.java
    projector.setDistance((int)(70));
    
    // This scales the picture with respect to the canvs
    // Sets "_2D_scale" in Projection_java
    //**************************************************************************
    projector.set2DScaling((int)(sfactor*13));
    //**************************************************************************
    
    // In Projection.java: factor = new_distance * _2D_scale
    
    //--------------------------------------------------------------------------
    //These set angles for initial condition of the x,y,z axes
    projector.setRotationAngle(45);//(45);
    projector.setAzimuthAngle(20);//polar angle, actually z axis is reference...
    
    //projector.setRotationAngle(0);
    //projector.setAzimuthAngle(0);//polar angle, actually z axis is reference...
    //--------------------------------------------------------------------------
    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.getRotationAngle() + (x - click_x);
    new_value = projector.getRotationAngle() + (x - click_x)*360/getSize().width;
    while (new_value > 360) new_value -= 360;
    while (new_value < 0) new_value += 360;
    projector.setRotationAngle(new_value);
    
    x_angle = new_value;
    //System.out.println("x_angle  "+x_angle);
    
    //new_value = projector.getAzimuthAngle() + (y - click_y);
    new_value = projector.getAzimuthAngle() + (y - click_y)*180/getSize().height;
    if (new_value > 180){new_value = 180;}
    else if (new_value < 0){new_value = 0;}
    projector.setAzimuthAngle(new_value);
    
    z_angle = new_value;
    //System.out.println("z_angle  "+z_angle);

    repaint();
    click_x = x;
    click_y = y;
    vector.jslider_x.setValue((int)x_angle);
    vector.jslider_z.setValue(180 - (int)z_angle);
    vector.repaint();
  }
  
  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                                  *
 *----------------------------------------------------------------------------------------*/

  
public 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;
              
        colore = Color.gray;
        if(!IsPower){
            color_line = color_line1;
        }
        else{
            color_line = color_line2;
        }
        
        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];
        
        //Make radiation pattern 
        double vposx1, vposy1, vposx2, vposy2, vposx3, vposy3, vposx4, vposy4, MaxZ;
        Array = new double[(latitude*5)+2][longitude+1];
        
        //3D Values
        xINT = new float[latitude*5+2][longitude+1];
        yINT = new float[latitude*5+2][longitude+1];
        zINT = new float[latitude*5+2][longitude+1];
        
        x3D = new float[latitude*5+2][longitude+1];
        y3D = new float[latitude*5+2][longitude+1];
        z3D = new float[latitude*5+2][longitude+1];
        z3DAux = new double[latitude*5+2][longitude+1];
        
        zTest = new double[latitude*5+2][longitude+1];
        
        //Patches on 2D projection
        Patchx1 = new double[latitude*5+2][longitude+1];
        Patchy1 = new double[latitude*5+2][longitude+1];
        Patchx2 = new double[latitude*5+2][longitude+1];
        Patchy2 = new double[latitude*5+2][longitude+1];
        Patchx3 = new double[latitude*5+2][longitude+1];
        Patchy3 = new double[latitude*5+2][longitude+1];
        
        float theta, phi;
        
        roty = (int)projector.getRotationAngle();
        rotx = (int)projector.getAzimuthAngle();
        
        
        for(i=0;i<(latitude*5);i++){
		theta=(float)(Math.PI*i/(float)(latitude*5));
                for(j=0;j<longitude;j++){
                    phi=(float)(Math.PI*j/(float)(longitude/2));
                    //Array[i][j] = Scale*(Math.sin(theta));//*Math.sin(theta));
                    
                    if(theta!=0.0f && Math.abs(theta)!=(float)(Math.PI) ){
                        
                        Array[i][j] = Math.pow(Scale*Complex.Magnitude(getHfield(theta,phi)), exponent);
                    }
                    else{
                        Array[i][j]=0.0;
                    }
                    
                    xINT[i][j] = (float)(Array[i][j]*Math.sin(theta)*Math.cos(phi));
                    yINT[i][j] = (float)(Array[i][j]*Math.sin(theta)*Math.sin(phi));
                    zINT[i][j] = (float)(Array[i][j]*Math.cos(theta));
                }
        }
        
        //g.setColor(Color.black);
        //g.fillRect(0,0,getSize().width,getSize().height);
        
        for(i=0;i<(latitude*5);i++){
            for(j=0;j<longitude;j++){
                x3D[i][j] = 0.0f;
                y3D[i][j] = 0.0f;
                z3D[i][j] = 0.0f;
            }
        }
        
        //Same scale for all plots
        double massimo;
        massimo = Scale/MaestroA.getMax(Array,latitude*5,longitude);
        tops = MaestroA.getMax(Array,latitude*5,longitude);
        
        for(i=0;i<(latitude*5);i++){
            for(j=0;j<longitude;j++){
                x3D[i][j] = xINT[i][j]*(float)massimo;
                y3D[i][j] = yINT[i][j]*(float)massimo;
                z3D[i][j] = zINT[i][j]*(float)massimo;
            }
        }  
        
         xRef = x3D[(latitude*5)/2][0];
         yRef = yRef = y3D[(latitude*5)/2][longitude/4];
         
         double Zmax = 0.0;
        //for(i=1;i<(latitude*5)/2;i++){
        //    for(j=0;j<longitude;j++){
        //       zTest[i][j] = Math.abs(z3D[i][j]);
        //    }
        //}
         
        ////Zmax = MaestroA.getMax(zTest);
        //Zmax = zTest[(int)(latitude*5/2)+2][(int)(longitude/2)+1];
        Zmax = Math.abs(z3D[(int)(latitude*5/2)+2][(int)(longitude/2)+1]);   
          
        // Calculate Patches nodes
        
        for(i=0;i<(latitude*5);i++){
		for(j=0;j<longitude;j++){
                    
                    projection = projector.project(x3D[i][j],y3D[i][j],z3D[i][j]);
                    vposx1 = (double)projection.x;
                    vposy1 = (double)projection.y;
                    projection = projector.project(x3D[i+1][j],y3D[i+1][j],z3D[i+1][j]);
                    vposx2 = (double)projection.x;
                    vposy2 = (double)projection.y;
                    
                    if(j<(longitude-1)){
                        projection = projector.project(x3D[i][j+1],y3D[i][j+1],z3D[i][j+1]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                    }
                    else{
                        projection = projector.project(x3D[i][0],y3D[i][0],z3D[i][0]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                    }
                    
                    Patchx1[i][j] = vposx1;
                    Patchy1[i][j] = vposy1;
                    Patchx2[i][j] = vposx2;
                    Patchy2[i][j] = vposy2;
                    Patchx3[i][j] = vposx3;
                    Patchy3[i][j] = vposy3;
                }
        }
        double plusDeg = projector.getAzimuthAngle();
        double plusRad = plusDeg *Math.PI/180.0;
        double plusDeg2 = projector.getRotationAngle();
        double Ant_Stick = 10.0;
          // draw antennas
        //draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(255,0,0), 0.5f); 
        //draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(0,150,0), 0.5f);
        
      //------------------------------------------------------------------------
      // draw axes labels
      //------------------------------------------------------------------------  
        projection = projector.project(axisL,0,0);     
        x[0] = projection.x; y[0] = projection.y;
        if (projection.x < x[0]){//DRAW THE X LABEL
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"x",Label.RIGHT,TOP, Color.black);
        }
        else{
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"x",Label.LEFT,TOP, Color.black);
        }
        
        projection = projector.project(0,axisL,0);     
        x[0] = projection.x; y[0] = projection.y;
        if (projection.x < x[0]){//DRAW Y LABEL
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.RIGHT,TOP, Color.black);
        }
        else{
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.LEFT,TOP, Color.black);
        }
        
        projection = projector.project(0,0,axisL);     
        x[0] = projection.x; y[0] = projection.y;
       
        if(projector.getAzimuthAngle() < 90){//DRAW Z LABEL
            outString(g,(int)(1.05*x[0]), (int)(1.0*y[0]),"z",Label.CENTER,CENTER, Color.black);
        }
        else{
            outString(g,(int)(1.05*x[0]), (int)(0.98*y[0]),"z",Label.CENTER,CENTER, Color.black);
        }
        
      
        //------------------------------------------------------------------------      
        //draw axes - Length is 15.0
        //------------------------------------------------------------------------
        int rule; 
        float alpha;
        rule = AlphaComposite.SRC_OVER;
          
        draw3DVector(g, axisL, 20, xRef, 0.0, 0.0, 18.0, 0.0, 0.0, thick2, Color.red); // x-axis
        if((plusDeg2 >= 0.0 && plusDeg2 <= 90) || (plusDeg2 >= 270.0 && plusDeg2 <= 360)){
            draw3DVector(g, axisL, 20, 0.0, yRef, 0.0, 0.0, 18.0, 0.0, thick2, Color.red);  // y-axis
        }
        else{
            //g2d.setComposite(AlphaComposite.getInstance(rule, 0.3f));
            draw3DVector(g, axisL, 20, 0.0, yRef, 0.0, 0.0, 18.0, 0.0, thick2, Color.red);  // y-axis
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
        }
      
        //  make axis portion inside 3D shape semi-transparent
        g2d.setComposite(AlphaComposite.getInstance(rule, 0.5f));
	  
        draw3DLine(g, axisL, 20, 0.0, 0.0, 0.0, xRef, 0.0, 0.0, thick2, Color.red); // x-axis              
        draw3DLine(g, axisL, 20, 0.0, 0.0, 0.0, 0.0, yRef, 0.0, thick2, Color.red);  // y-axis
      
        // draw obscured portion of X and Z axes
        draw3DVector(g, axisL, 20, xRef, 0.0, 0.0, 18.0, 0.0, 0.0, thick2, Color.red); // x-axis
        draw3DLine(g, axisL, 0, 0.0, 0.0, (double)Zmax, 0.0, 0.0, 0.0, thick2, Color.red); // z-axis
      
        g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
        //------------------------------------------------------------------------
        // draw wireframe
        //------------------------------------------------------------------------
        int endit;
        int size1 = 1;
        int size2 = 0;
        endit = longitude;
        
        if(!IsPatchOn){
           for(i=0;i<(latitude*5);i++){
             for(j=0;j<endit;j++){
             //for(j=0;j<3;j++){
                    drawLineThick(g, Patchx1[i][j], Patchy1[i][j], Patchx2[i][j], Patchy2[i][j], size1, color_line);
                    
                    if(j==(endit-1)){
                        drawLineThick(g, Patchx1[i][j+1], Patchy1[i][j+1], Patchx2[i][j+1], Patchy2[i][j+1], size1, color_line);
                    }
                    
                    if(dipolelength < 5.0){
                    
                        if(i==9 || i==19  || i==29 || i==39 || i==49 || i==59 ||
                           i==69 || i==79 || i==89 || i==99 || i==109 || i==119 || i==129 ||
                           i==139 || i==149 || i==159 || i==169 || i==179 || i==189 || 
                           i==199 || i==209 || i==219 || i==229 || i==239 || i==249 ||
                           i==259 || i==269 || i==279 || i==289 || i==299 || i==309 ||
                           i==319 || i==329 || i==339 || i==349 || i==359 || i==369 ||
                           i==379 || i==389 || i==399 || i==409 || i==419 || i==429 ||
                           i==439 || i==449)

                         {
                            drawLineThick(g, Patchx1[i][j], Patchy1[i][j], Patchx3[i][j], Patchy3[i][j], size1, color_line);
                            //diagonal of patch (forms the two triangles)
                            ////drawLineThick(g, Patchx2[i][j], Patchy2[i][j], Patchx3[i+10][j], Patchy3[i+10][j], 1, Color.lightGray);
                        }
                    }
                    else{
                         if(i==4 || i==14  || i==24 || i==34 || i==44 || i==54 ||
                           i==69 || i==74 || i==84 || i==94 || i==104 || i==114 || i==124 ||
                           i==134 || i==144 || i==154 || i==164 || i==174 || i==184 || 
                           i==194 || i==204 || i==214 || i==224 || i==234 || i==244 ||
                           i==254 || i==264 || i==274 || i==284 || i==294 || i==304 ||
                           i==314 || i==324 || i==334 || i==344 || i==354 || i==364 ||
                           i==374 || i==384 || i==394 || i==404 || i==414 || i==424 ||
                           i==434 || i==444 ||
                           i==9 || i==19  || i==29 || i==39 || i==49 || i==59 ||
                           i==69 || i==79 || i==89 || i==99 || i==109 || i==119 || i==129 ||
                           i==139 || i==149 || i==159 || i==169 || i==179 || i==189 || 
                           i==199 || i==209 || i==219 || i==229 || i==239 || i==249 ||
                           i==259 || i==269 || i==279 || i==289 || i==299 || i==309 ||
                           i==319 || i==329 || i==339 || i==349 || i==359 || i==369 ||
                           i==379 || i==389 || i==399 || i==409 || i==419 || i==429 ||
                           i==439 || i==449)

                         {
                            drawLineThick(g, Patchx1[i][j], Patchy1[i][j], Patchx3[i][j], Patchy3[i][j], size1, color_line);
                            //diagonal of patch (forms the two triangles)
                            ////drawLineThick(g, Patchx2[i][j], Patchy2[i][j], Patchx3[i+10][j], Patchy3[i+10][j], 1, Color.lightGray);
                        }   
                    }
                }        
            }
        }
      //------------------------------------------------------------------------
      // draw axes labels
      //------------------------------------------------------------------------
        projection = projector.project(axisL,0,0);     
        x[0] = projection.x; y[0] = projection.y;
        if (projection.x < x[0]){//DRAW THE X LABEL
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"x",Label.RIGHT,TOP, Color.black);
        }
        else{
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"x",Label.LEFT,TOP, Color.black);
        }
        
        projection = projector.project(0,axisL,0);     
        x[0] = projection.x; y[0] = projection.y;
        if (projection.x < x[0]){//DRAW Y LABEL
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.RIGHT,TOP, Color.black);
        }
        else{
            outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.LEFT,TOP, Color.black);
        }
        
        //------------------------------------------------------------------------      
        //draw axes - Length is 15.0
        //------------------------------------------------------------------------        
        //draw3DLine(g, axisL, 20, 0.0, 0.0, 0.0, 15.0, 0.0, 0.0, thick1, Color.black); // x-axis              
        //draw3DVector(g, axisL, 20, xRef, 0.0, 0.0, 18.0, 0.0, 0.0, thick2, Color.red); // x-axis
      
        //draw3DLine(g, axisL, 20, 0.0, 0.0, 0.0, 0.0, 15.0, 0.0, thick1, Color.black);  // y-axis
        //draw3DVector(g, axisL, 20, 0.0, yRef, 0.0, 0.0, 18.0, 0.0, thick2, Color.red);  // y-axis
      
        //draw unobstructed portion of Z axis
      
        draw3DVector(g, axisL, 20, 0.0, 0.0, (double)Zmax, 0.0, 0.0, 17.0, thick2, Color.red);// z-axis
      
        if(ShowDipoles){
            
            //Lines Connecting ends of opposite antennas
            draw3DLine(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 1, new Color(0,0,200));
            draw3DLine(g, axisL, 0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, 1, new Color(0,0,200));
            
            if((plusDeg2 >= 90.0 && plusDeg2 <= 270)){
                draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(255,0,0), 0.6f);
                //bottom
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(210,0,0));
                //top
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.red);
                
                draw3DVector(g, axisL, 20, 0.0, 0.0, (double)Zmax, 0.0, 0.0, 17.0, thick2, Color.red);// z-axis
                 
                draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(0,150,0), 0.6f);
                //bottom
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
                g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));

                //top
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
            }
            else{
                draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(0,150,0), 0.6f);
                //bottom
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
                g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
                //top
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
                
                draw3DVector(g, axisL, 20, 0.0, 0.0, (double)Zmax, 0.0, 0.0, 17.0, thick2, Color.red);// z-axis
                
                draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(255,0,0), 0.6f);
                //bottom
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(210,0,0));
                //top
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.red);
            }
            
            
            /*
            draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(255,0,0), 0.6f);
            //bottom
            fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(210,0,0));
            //top
            fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
            drawCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.red);
                
            
            draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(0,150,0), 0.6f);
            //bottom
            fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
            g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));

            //top
            fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
            drawCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
            */
        }
        // transparency = 1.0 is totally opaque
        // transparency = 0.0 is fully transparent
        float transparency = 0.1f;
     
        //-------------------------------------------------------------------------        
        if(IsPatchOn){
            //draw patches & wireframe - no hidden lines/patches algorithm here
            // bottom half
         
            for(i=(latitude*5)-1;i>(latitude*5)/2;i--){
            	//for(j=0;j<longitude;j++){
                for(j=longitude-1;j>-1;j--){
                   
                    projection = projector.project(x3D[i][j],y3D[i][j],z3D[i][j]);
                    vposx1 = (double)projection.x;
                    vposy1 = (double)projection.y;
                    projection = projector.project(x3D[i+1][j],y3D[i+1][j],z3D[i+1][j]);
                    vposx2 = (double)projection.x;
                    vposy2 = (double)projection.y;
                                
                    if(j<(longitude-1)){
                        projection = projector.project(x3D[i][j+1],y3D[i][j+1],z3D[i][j+1]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][j+1],y3D[i+1][j+1],z3D[i+1][j+1]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    else{
                        projection = projector.project(x3D[i][0],y3D[i][0],z3D[i][0]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][0],y3D[i+1][0],z3D[i+1][0]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    
                    double docolor = Math.abs(Array[i][j]/tops);                   
                    //if(docolor > 1.0){docolor = 1.0;} 
                    docolor = 1.0;
                    Color colorpatch = new Color(0,(int)(docolor*255),(int)(docolor*255));
                    
                    // vertical lines
                    drawLineThick(g, vposx1, vposy1, vposx2, vposy2, 1, color_line);
                    if(vposx1 > vposx3 && vposy1 > vposy2){
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, 1, color_line);
                    }
                    else{
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, 1, color_line);
                    }
                    
                    // horizontal lines
                    if(i==9 || i==19  || i==29 || i==39 || i==49 || i==59 ||
                       i==69 || i==79 || i==89 || i==99 || i==109 || i==119 || i==129 ||
                       i==139 || i==149 || i==159 || i==169 || i==179 || i==189 || 
                       i==199 || i==209 || i==219 || i==229 || i==239 || i==249 ||
                       i==259 || i==269 || i==279 || i==289 || i==299 || i==309 ||
                       i==319 || i==329 || i==339 || i==349 || i==359 || i==369 ||
                       i==379 || i==389 || i==399 || i==409 || i==419 || i==429 ||
                       i==439 || i==449)
                    
                        if(vposx1 > vposx3 && vposy1 > vposy2){
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, 1, color_line);
                        }
                        else{
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, 1, color_line);
                        }
                    
                    
                }
            }  
        
            // top half
            for(i=(latitude*5)/2;i>-1;i--){
            	//for(j=0;j<longitude;j++){
                for(j=longitude-1;j>longitude/2-1;j--){
                    
                    projection = projector.project(x3D[i][j],y3D[i][j],z3D[i][j]);
                    vposx1 = (double)projection.x;
                    vposy1 = (double)projection.y;
                    projection = projector.project(x3D[i+1][j],y3D[i+1][j],z3D[i+1][j]);
                    vposx2 = (double)projection.x;
                    vposy2 = (double)projection.y;
                                
                    if(j<(longitude-1)){
                        projection = projector.project(x3D[i][j+1],y3D[i][j+1],z3D[i][j+1]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][j+1],y3D[i+1][j+1],z3D[i+1][j+1]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    else{
                        projection = projector.project(x3D[i][0],y3D[i][0],z3D[i][0]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][0],y3D[i+1][0],z3D[i+1][0]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    double docolor = Math.abs(Array[i][j]/tops);
                    //if(docolor > 1.0){docolor = 1.0;}
                    docolor = 1.0;
                    Color colorpatch = new Color(0,(int)(docolor*255),(int)(docolor*255));
                    
                    // vertical lines
                    drawLineThick(g, vposx1, vposy1, vposx2, vposy2, 1, color_line);
                    if(vposx1 > vposx3 && vposy1 > vposy2){
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick1, color_line);
                    }
                    else{
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick1, color_line);
                    }
                    
                    // horizontal lines
                    if(i==9 || i==19  || i==29 || i==39 || i==49 || i==59 ||
                       i==69 || i==79 || i==89 || i==99 || i==109 || i==119 || i==129 ||
                       i==139 || i==149 || i==159 || i==169 || i==179 || i==189 || 
                       i==199 || i==209 || i==219 || i==229 || i==239 || i==249 ||
                       i==259 || i==269 || i==279 || i==289 || i==299 || i==309 ||
                       i==319 || i==329 || i==339 || i==349 || i==359 || i==369 ||
                       i==379 || i==389 || i==399 || i==409 || i==419 || i==429 ||
                       i==439 || i==449)
                    {
                        if(vposx1 > vposx3 && vposy1 > vposy2)
                        {
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick1, color_line);
                        }
                        else
                        {
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick1, color_line);
                        }
                    }
                    
                }
            }
        
            for(i=0;i<(latitude*5)/2+1;i++){
            	//for(j=0;j<longitude/2;j++){
                for(j=longitude/2-1;j>-1;j--){
                    
                    projection = projector.project(x3D[i][j],y3D[i][j],z3D[i][j]);
                    vposx1 = (double)projection.x;
                    vposy1 = (double)projection.y;
                    projection = projector.project(x3D[i+1][j],y3D[i+1][j],z3D[i+1][j]);
                    vposx2 = (double)projection.x;
                    vposy2 = (double)projection.y;
                                
                    if(j<(longitude-1)){
                        projection = projector.project(x3D[i][j+1],y3D[i][j+1],z3D[i][j+1]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][j+1],y3D[i+1][j+1],z3D[i+1][j+1]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    else{
                        projection = projector.project(x3D[i][0],y3D[i][0],z3D[i][0]);
                        vposx3 = (double)projection.x;
                        vposy3 = (double)projection.y;
                        projection = projector.project(x3D[i+1][0],y3D[i+1][0],z3D[i+1][0]);
                        vposx4 = (double)projection.x;
                        vposy4 = (double)projection.y;
                    }
                    double docolor = Math.abs(Array[i][j]/tops);
                    //if(docolor > 1.0){docolor = 1.0;}
                    docolor = 1.0;
                    
                    Color colorpatch = new Color(0,(int)(docolor*255),(int)(docolor*255));
                    
                    // vertical lines
                    drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick1, color_line);
                    if(vposx1 > vposx3 && vposy1 > vposy2){
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick1, color_line);
                    }
                    else{
                        FillPatch(g, vposx1, vposy1, vposx2, vposy2, 
                                 vposx3, vposy3, vposx4, vposy4, 
                                 transparency, colorpatch);
                        drawLineThick(g, vposx1, vposy1, vposx2, vposy2, thick1, color_line);
                    }
                    
                    // horizontal lines
                    if(i==9 || i==19  || i==29 || i==39 || i==49 || i==59 ||
                       i==69 || i==79 || i==89 || i==99 || i==109 || i==119 || i==129 ||
                       i==139 || i==149 || i==159 || i==169 || i==179 || i==189 || 
                       i==199 || i==209 || i==219 || i==229 || i==239 || i==249 ||
                       i==259 || i==269 || i==279 || i==289 || i==299 || i==309 ||
                       i==319 || i==329 || i==339 || i==349 || i==359 || i==369 ||
                       i==379 || i==389 || i==399 || i==409 || i==419 || i==429 ||
                       i==439 || i==449)
                    {
                        if(vposx1 > vposx3 && vposy1 > vposy2)
                        {
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick1, color_line);
                        }
                        else
                        {
                            drawLineThick(g, vposx1, vposy1, vposx3, vposy3, thick1, color_line);
                        }
                    }
                }
            }
        }
        //System.out.println(plusDeg+"   "+plusDeg2);
        
        double mycx = sfactor * 28.0;
        double mycx2 = (double)getSize().width - sfactor * 28.0;
        double mycy =  (double)getSize().height - sfactor * 28.0;
        double mycy2 = sfactor * 28.0;
        double radio = sfactor * 20.0;
        
        // ANGLE MAPS - MANUAL ROTATION
        // x-axis
        drawLineThick(g, mycx + radio, mycy, mycx - radio, mycy, 1, Color.lightGray);
        //arrow
        //drawLineThick(g, mycx - radio*1.4, mycy, mycx - radio*1.4 + 6, mycy-3, 1, Color.lightGray);
        //drawLineThick(g, mycx - radio*1.4, mycy, mycx - radio*1.4 + 6, mycy+3, 1, Color.lightGray);
        
        // y-axis
        drawLineThick(g, mycx, mycy + radio, mycx, mycy - radio, 1, Color.lightGray);
        
        FillArcTransp(g, mycx, mycy, radio, 180.0, x_angle, Color.yellow, 0.5);
        drawLineThick(g, mycx, mycy, mycx - (radio*1.2)*Math.cos(x_angle*Math.PI/180.0), mycy + (radio*1.2)*Math.sin(x_angle*Math.PI/180.0), 2, Color.black);
        drawCircleThick(g, mycx, mycy, radio, 2, Color.gray);
        
        // ANGLE MAPS - MANUAL ROTATION  =======================================
        double x_shift = radio * 2.0;
        // half x-axis
        drawLineThick(g, mycx2 + radio, mycy2, mycx2, mycy2, 1, Color.lightGray);
        
        //z-axis
        drawLineThick(g, mycx2 , mycy2 + radio, mycx2, mycy2 - radio, 1, Color.lightGray);
        
        FillArcTransp(g, mycx2, mycy2, radio, 90.0, -z_angle, Color.yellow, 0.5);
        DrawArcTransp(g, mycx2, mycy2, radio, 270.0, 180, Color.black, 1.0, 1);
        drawLineThick(g, mycx2, mycy2, mycx2 - (radio*1.2)*Math.cos((270 - z_angle)*Math.PI/180.0), mycy2 + (radio*1.2)*Math.sin((270 - z_angle)*Math.PI/180.0), 2, Color.black);
        
        //MaestroG.subscripter("x","","",g,(int)Math.ceil(sfactor*12),(int)(mycx/3),(int)(mycy/2));
        //MaestroG.subscripter("z","","",g,(int)Math.ceil(sfactor*12),(int)(2.6*mycx),(int)(mycy/2));
        if(x_angle >= 360.0){
            x_angle = 0.0;
            MaestroG.subscripter("x","","",g,(int)Math.ceil(sfactor*10.5),(int)(mycx*58/30),(int)(mycy + 0.2*radio));
            MaestroG.subscripter(""+x_angle+"\u00B0","","",g,(int)Math.ceil(sfactor*10.5),(int)(mycx*58/30),(int)(mycy + 0.9*radio));
        }
        else{
            MaestroG.subscripter("x","","",g,(int)Math.ceil(sfactor*10.5),(int)(mycx*58/30),(int)(mycy + 0.2*radio));
            MaestroG.subscripter(""+x_angle+"\u00B0","","",g,(int)Math.ceil(sfactor*10.5),(int)(mycx*58/30),(int)(mycy + 0.9*radio));
        }
        MaestroG.subscripter("z","","",g,(int)Math.ceil(sfactor*10.5),(int)(getSize().width - sfactor * 40.0),(int)(mycy2 * 24/40 ));
        MaestroG.subscripter(""+z_angle+"\u00B0","","",g,(int)Math.ceil(sfactor*10.5),(int)(getSize().width - sfactor * 40.0),(int)(mycy2 * 90/40 ));
        
        //======================================================================
        //PAINT DIPOLES IN FOREGROUND
        /*
        if(ShowDipoles){
            
            if((plusDeg2 >= 0.0 && plusDeg2 <= 90) || (plusDeg2 >= 270.0 && plusDeg2 <= 360)){
                draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(255,0,0), 0.01f);
                projection = projector.project(0,axisL,0);     
                x[0] = projection.x; y[0] = projection.y;
                if (projection.x < x[0]){//DRAW Y LABEL
                    outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.RIGHT,TOP, Color.black);
                }
                else{
                    outString(g,(int)(x[0]), (int)(1.02*y[0]),"y",Label.LEFT,TOP, Color.black);
                }
                
                //private void fillCircleHorizontalThick(Graphics g, double xCenter, double yCenter, double zCenter, double Radius, int thick, Color color){
                //bottm
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(210,0,0));
                //top
                fillCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.red);
            }
            
        }
        */
        
        /*
            else{
                draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), -Ant_Stick/2.0, thick2*10, new Color(0,150,0), 0.8f);
                //bottm
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), -Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
                //top
                fillCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, Color.white);
                drawCircleHorizontalThick(g, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.45, 1, new Color(0,150,0));
                
            }
            
            //Fixed Circular tips as very short white line(no perspective - this is a trick)
            //draw3DLine2(g, axisL, 0, 0.0, -15.0*(distancia), Ant_Stick/2.0, 0.0, -15.0*(distancia), Ant_Stick/2.0, thick2*8, new Color(240,240,240), 1.0f);
            //draw3DLine2(g, axisL, 0, 0.0, 15.0*(distancia), Ant_Stick/2.0, 0.0, 15.0*(distancia), Ant_Stick/2.0, thick2*8, new Color(240,240,240), 1.0f);
            
        } 
        
        // TEST CIRCLE AT ORIGIN
        //private void drawCircleHorizontalThick(Graphics g, double xCenter, double yCenter, double zCenter, double Radius, int thick, Color color){
        //drawCircleHorizontalThick(g, 0.0, 0.0, 0.0, 1.0, 1, Color.red);
        //private void fillCircleHorizontalThick(Graphics g, double xCenter, double yCenter, double zCenter, double Radius, int thick, Color color){
        //fillCircleHorizontalThick(g, 0.0, 0.0, 0.0, 0.95, 1, Color.white);
      */  
        
    }

    //----------------------------------------------------------------------------
    private final void outString(Graphics g, int x, int y, String s, int x_align, int y_align, Color colore) {
        g.setColor(colore);
        g.setFont(new Font("SanSerif",Font.BOLD,(int)sfactor*24));
        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;
        }     
    }
  
    public Complex getHfield(double theta, double phi){
	int i;
	double targ1, targ2, targ3, targa, targb, factor1, factor2;
	Complex myhfield, carga, cargb, complex1, complex2, array_factor;
	double my_phase = - fase * Math.PI/180.0;
	factor1 = 2.0*Math.PI*distancia*Math.sin(theta)*Math.sin(phi)-my_phase;
	factor2 = number_dipoles * factor1;
	
	complex1 = new Complex(1.0 - Math.cos(factor2),- Math.sin(factor2));
	complex2 = new Complex(1.0 - Math.cos(factor1),- Math.sin(factor1));
	
	    if(Complex.Magnitude(complex2) == 0.0){
		array_factor = new Complex(number_dipoles,0.0);
	    }
	    else{
		array_factor = Complex.Divide(complex1, complex2);
	    }
	
	if(dipolelengthA<0.5f){
		scalingA=(float)(1.0/Math.sin(Math.PI*(dipolelengthA)));
	}
	else{
		scalingA=1.0f;
	}
	
	
	/*
	if(dipolelengthA<0.0){
		if(dipolelengthA > 0.0){
		scalingA=(double)(1.0/Math.sin(Math.PI*(dipolelengthA)));
		}
		else{
		    scalingA=(double)(1.0/Math.sin(Math.PI*(dipolelengthA+0.000001)));
		}
	}
	else{
		scalingA=1.0;
	}
	*/
	
	//Avoid sin(theta)=0.0 situation
	if(theta!=0.0 && Math.abs(theta)!=(double)(Math.PI) ){
	  targ1=Math.PI*distancia*Math.sin(theta)*Math.sin(phi)-my_phase/2.0-2.0*Math.PI*R;
	  targ2=Math.PI*distancia*Math.sin(theta)*Math.sin(phi)-my_phase/2.0+2.0*Math.PI*R;
	  targ3=1.0/(2.0*Math.PI*R*Math.sin(theta));
	  
	  if (dipolelengthA > 0.0){
	    targa=dipolecurrentA*scalingA*(Math.cos(Math.PI*dipolelengthA*Math.cos(theta))
                                        -Math.cos(Math.PI*dipolelengthA));
	  }
	  else{
	    targa=dipolecurrentA*scalingA*(Math.cos(Math.PI*(dipolelengthA+0.000001)*Math.cos(theta))
                                        -Math.cos(Math.PI*(dipolelengthA+0.000001)));
	  }	
	  
	  carga=new Complex(-Math.sin(targ1),Math.cos(targ1));
	  	
	  carga.Multiply(targa);
	  
	  myhfield=new Complex(0.0,0.0);
	  myhfield.Add(carga);
	  myhfield.Multiply(targ3);
	  myhfield.Multiply(array_factor);
	}
	else{
		myhfield=new Complex(0.0,0.0);
	}

	  return(myhfield);
}

public double getHfield_mag(double theta, double phi){
	int i;
	double targ1, targ2, targ3, targa, targb, factor1, factor2;
	Complex myhfield, carga, cargb, complex1, complex2, array_factor;
        double my_phase = - fase * Math.PI/180.0;
        
	factor1 = 2.0*Math.PI*distancia*Math.sin(theta+0.0001)*Math.sin(phi+0.0001)-my_phase;
	factor2 = number_dipoles * factor1;
	
	complex1 = new Complex(1.0 - Math.cos(factor2),- Math.sin(factor2));
	complex2 = new Complex(1.0 - Math.cos(factor1),- Math.sin(factor1));
	
	    if(Complex.Magnitude(complex2) == 0.0){
		array_factor = new Complex(number_dipoles,0.0);
	    }
	    else{
		array_factor = Complex.Divide(complex1, complex2);
	    }
	 
	if(dipolelengthA<0.5f){
		scalingA=(float)(1.0/Math.sin(Math.PI*(dipolelengthA)));
	}
	else{
		scalingA=1.0f;
	}
	
	/*   
	if(dipolelengthA<0.0){
		if(dipolelengthA > 0.0){
		scalingA=(double)(1.0/Math.sin(Math.PI*(dipolelengthA)));
		}
		else{
		    scalingA=(double)(1.0/Math.sin(Math.PI*(dipolelengthA+0.000001)));
		}
	}
	else{
		scalingA=1.0;
	}
	*/
	
	//Avoid sin(theta)=0.0 situation
	if(theta!=0.0 && Math.abs(theta)!=(double)(Math.PI) ){
	  targ1=Math.PI*distancia*Math.sin(theta)*Math.sin(phi)-my_phase/2.0-2.0*Math.PI*R;
	  targ2=Math.PI*distancia*Math.sin(theta)*Math.sin(phi)-my_phase/2.0+2.0*Math.PI*R;
	  targ3=1.0/(2.0*Math.PI*R*Math.sin(theta));
	  
	  if (dipolelengthA > 0.0){
	    targa=dipolecurrentA*scalingA*(Math.cos(Math.PI*dipolelengthA*Math.cos(theta))
                                        -Math.cos(Math.PI*dipolelengthA));
	  }
	  else{
	    targa=dipolecurrentA*scalingA*(Math.cos(Math.PI*(dipolelengthA+0.000001)*Math.cos(theta))
                                        -Math.cos(Math.PI*(dipolelengthA+0.000001)));
	  }	
	  
	  carga=new Complex(-Math.sin(targ1),Math.cos(targ1));
	  	
	  carga.Multiply(targa);
	  
	  myhfield=new Complex(0.0,0.0);
	  myhfield.Add(carga);
	  myhfield.Multiply(targ3);
	  myhfield.Multiply(array_factor);
	}
	else{
		myhfield=new Complex(0.0,0.0);
	}

	  return(Complex.Magnitude(myhfield));
}

  
    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
          
          // dash line
          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 draw3DLine(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;
          
          Graphics2D g2d = (Graphics2D)g;
          g2d.setPaint(colore);
          //g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
           g2d.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER));
           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, (int)Math.ceil(sfactor*3), colore); // JAVA 2D GRAPHICS - needs double values
          
            //----------------------------------------------------------------------     
            //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
  
    private void draw3DLine2(Graphics g, float axisL, int tip_ratio, double vx1, double vy1, double vz1, double vx2, double vy2, double vz2, int thick, Color colore, float myalpha){
          
          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.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER));
          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
          int rule; 
          float alpha;
          alpha = myalpha;
          rule = AlphaComposite.SRC_OVER;
          g2d.setComposite(AlphaComposite.getInstance(rule, alpha));
          drawLineThick(g, vposx, vposy, vtipx, vtipy, thick, colore); // JAVA 2D GRAPHICS - needs double values
          g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
            //----------------------------------------------------------------------     
            //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 coplanar 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 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 void DrawArcTransp(Graphics g, double xCenter, double yCenter, double Radius, double startangle, double endangle, Color color, double alphachan, int thick){
	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.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER));
        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.draw(arc_one);
  
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
        g2d.setComposite(AlphaComposite.getInstance(rule, 1.0f));
        g2d.setStroke(new BasicStroke(1));
    }
  
    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.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER));
        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.setStroke(new BasicStroke(thick,BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER));
        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.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(vposx-rado,vposy-rado*Math.sin(Math.PI/180.0*
                projector.getAzimuthAngle()),2*rado,(2*rado)*Math.sin(Math.PI/180.0*projector.getAzimuthAngle()));
        g2d.draw(circle);
        g2d.setStroke(new BasicStroke(1));
        //g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }
    
    private void fillCircleHorizontalThick(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.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(vposx-rado,vposy-rado*Math.sin(Math.PI/180.0*
                projector.getAzimuthAngle()),2*rado,(2*rado)*Math.sin(Math.PI/180.0*projector.getAzimuthAngle()));
        g2d.fill(circle);
        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);
    }
    
    public void resetRotationAngle(int newangle){
        
        projector.setRotationAngle(newangle);
    }
    
    public void resetAzimuthAngle(int newangle){
        
        projector.setAzimuthAngle(newangle);
    }
}