/*
 * A Java Applet Used to Draw Mohr's Circle in a Plane for Stress Analysis 
 * 
found at:
http://www.aoe.vt.edu/~jing/MohrCircle.html

 * This Java applet can be used to draw Mohr's circle and stress analysis 
 * in a Plane. It is used for educational purpose.
 *
 */
import java.awt.*;
import java.applet.*;

public class Mohr extends Applet {
        int xp = 0;
        int yp = 0;
	  	double  dsigma_x;	    
	    double  dsigma_y;
        double  dtau_xy;
        double  dradius;
        double  dsigma_ave;	    
	    double  dsigma_1;
        double  dsigma_2;
        double  dtheta_p; 
        double  dsigma_mis;      
        String  filled;
    MohrControls controls;

    public void init() {
	setLayout(new BorderLayout());
	MohrCanvas c = new MohrCanvas();
	add("Center", c);
	add("South", controls = new MohrControls(c));
    }

    public void start() {
	controls.enable();
    }

    public void stop() {
	controls.disable();
    }

    public boolean handleEvent(Event e) {
	if (e.id == Event.WINDOW_DESTROY) {
	    System.exit(0);
	}
	return false;
    }

    public static void main(String args[]) {
	Frame f = new Frame("Mohr's Circle");
	Mohr mohr = new Mohr();

	mohr.init();
	mohr.start();

	f.add("Center", mohr);
	f.resize(543, 363);
	f.show();
    }
    
}
    
class MohrCanvas extends Canvas {  
    int     radius = 0; 
    int		xx = 0;
    int		yy = 0;
    double  drr;
    double  dxx;
    double  dyy;
	double  dsigma_x;	    
	double  dsigma_y;
    double  dtau_xy;    
	double  dradius;	    
    double  dsigma_ave;	    
	double  dsigma_1;
    double  dsigma_2;
    double  dtheta_p;
    double  dsigma_mis;   
    String	filled = "draw";
    Font	font;
    int xp ;
    int yp;
    

    public void paint(Graphics g) {

	Rectangle r = bounds();

	int glines = 1;
	int dlines = 15;
	
	int hlines = r.height / glines;
	int vlines = r.width / glines;
	int two_x_0 = vlines * glines;
	int two_y_0 = hlines * glines;

/*
 * Draw grid lines as a bacground of the window
 * 
 *
 *	g.setColor(Color.pink);
 *	for (int i = 1; i <= hlines / 2 +1; i++) {
 *	    g.drawLine(0, two_y_0 / 2 + i * glines, two_x_0 , 
 *	              two_y_0 / 2 + i * glines);
 *	    g.drawLine(0, two_y_0 / 2 - i * glines, two_x_0 , 
 *	              two_y_0 / 2 - i * glines);
 *	}
 *	for (int i = 1; i <= vlines / 2 +1; i++) {
 *	    g.drawLine(two_x_0 / 2 + i * glines, 0, 
 *	               two_x_0 / 2 +  i * glines, two_y_0);
 *	    g.drawLine(two_x_0 / 2 - i * glines, 0, 
 *	               two_x_0 / 2 -  i * glines, two_y_0);
 *	}
 */

/*
 * Calculate the scaled data for Mohr's circle and the unit per division
 */ 
	       
    double dunit = 1.0d;
    double dscalar = 1.0d;

    drr = dradius * ((double)dlines / dunit);
    dxx = dsigma_ave * ((double)dlines / dunit);
    dyy = 0.0d;
    
    double dsigxx = dsigma_x * ((double)dlines / dunit);
    double dsigyy = dsigma_y * ((double)dlines / dunit);    
    double dtauxy = dtau_xy * ((double)dlines / dunit);  
      
    if(drr >= (double)dlines) { 
       dscalar = 10.0d;
    } else { 
            dscalar = 0.1d;
      }
    
    if(drr > 1.e-300) {while(2.0d * drr > (double)r.height - 30.0d){
                                         dunit = dscalar * dunit;
                                         drr = drr / dscalar;
                                         dxx = dxx / dscalar;
                                         dsigxx = dsigxx / dscalar;
                                         dsigyy = dsigyy / dscalar;                                         
                                         dtauxy = dtauxy / dscalar;
                       }                   
    } 
    if(drr > 1.e-300 ) {while(drr < (double)dlines){
                                         dunit = dscalar * dunit;
                                         drr = drr / dscalar;
                                         dxx = dxx / dscalar; 
                                         dsigxx = dsigxx / dscalar; 
                                         dsigyy = dsigyy / dscalar;                                        
                                         dtauxy = dtauxy / dscalar;                          
                       }
    }                                   

    double km = 1.0d;  

	if(filled.equals("size 1")) { 
	   if(4 * (int)drr <= r.height ) {
	     dlines = 2 * dlines;	     
	     km = 2.0d;	     
	   }
	}
	
	if(filled.equals("size 2")) { 
	   if(8 * (int)drr <= r.height ) {
	     dlines = 4 * dlines;
	     km = 4.0d;
	   } else { 
	           if(4 * (int)drr <= r.height ) {
	             dlines = 2 * dlines;	     
	             km = 2.0d;
	           }	 	   
	     }
	}                                  
                                      
    radius = (int)(km * drr);
    xx = (int)(km * dxx);
    yy = 0;
    int sxx = (int)(km * dsigxx);
    int syy = (int)(km * dsigyy);
    int txy = (int)(km * dtauxy);
    

    int nxxoff = 0;
    
    while( 2 * (xx + radius) > r.width - 90) {
         xx = xx - dlines;
         sxx = sxx - dlines; 
         syy = syy - dlines;                  
         nxxoff = nxxoff + 1;
    }

    while( 2 * (xx - radius) < - r.width) {
         xx = xx + dlines;
         sxx = sxx + dlines; 
         syy = syy + dlines;              
         nxxoff = nxxoff - 1;
    }  
    
    
    
                                            

/*
 * Draw Mohr's circle, filled or not
 */
       
	g.setColor(Color.red);
	if (filled.equals("Fill")) {
	    g.fillArc(two_x_0 / 2-radius+xx, two_y_0 / 2 -radius-yy, 
	              radius+radius, radius+radius, 0, 360);

	}  else { 
	    g.drawArc(two_x_0 / 2-radius+xx, two_y_0 / 2 -radius-yy, 
	              radius+radius, radius+radius, 0, 360);
	   }
	   
		   g.setColor(Color.green);

	     g.fillArc(two_x_0 / 2-radius+xx, two_y_0 / 2 -radius-yy, 
	               radius+radius, radius+radius, 0, -2 * (int)dtheta_p);
	     
	     g.drawLine(two_x_0 / 2+sxx, two_y_0 / 2 +txy, 
	               two_x_0 / 2+syy , two_y_0 / 2 -txy);
  

	g.setColor(Color.blue);	   
	g.drawOval(two_x_0 / 2+xx-radius-2, two_y_0 / 2-2, 4, 4); 
	g.drawOval(two_x_0 / 2+xx+radius-2, two_y_0 / 2-2, 4, 4);
	g.drawOval(two_x_0 / 2+xx-2, two_y_0 / 2 +radius-2, 4, 4); 
	g.drawOval(two_x_0 / 2+xx-2, two_y_0 / 2 -radius-2, 4, 4);
	g.drawOval(two_x_0 / 2+xx-2, two_y_0 / 2 -2, 4, 4);
	g.setColor(Color.white);
	g.drawOval(two_x_0 / 2+sxx-2, two_y_0 / 2 -txy-2, 4, 4);	  
	g.drawOval(two_x_0 / 2+syy-2, two_y_0 / 2 -txy-2, 4, 4);
	g.drawOval(two_x_0 / 2+sxx-2, two_y_0 / 2 +txy-2, 4, 4);	  
	g.drawOval(two_x_0 / 2+syy-2, two_y_0 / 2 +txy-2, 4, 4);	
	
/*
 * Draw axis lines with the center of the window as origin
 */ 
    g.setColor(Color.black);
    g.drawLine(0, two_y_0 / 2, two_x_0 , two_y_0 / 2);
	g.drawLine(two_x_0 / 2, 0, two_x_0 / 2, two_y_0);


/*
 * Draw disivion lines/points along axises
 */ 

    	 
	g.setColor(Color.pink);
	for (int i = 1; i <= hlines / 2 +1; i++) {
	    g.drawLine(0, two_y_0 / 2 + i * dlines, two_x_0 , 
	               two_y_0 / 2 + i * dlines);
	    g.drawLine(0, two_y_0 / 2 - i * dlines, two_x_0 , 
	               two_y_0 / 2 - i * dlines);
	}
	for (int i = 1; i <= vlines / 2 +1; i++) {
	    g.drawLine(two_x_0 / 2 + i * dlines, 0, 
	               two_x_0 / 2 +  i * dlines, two_y_0);
	    g.drawLine(two_x_0 / 2 - i * dlines, 0, 
	               two_x_0 / 2 -  i * dlines, two_y_0);
	}
	
    g.setColor(Color.black);
    for (int i = 1; i <= hlines / 2 +1; i++) {
	    g.drawLine(two_x_0 / 2, two_y_0 / 2 + i * dlines, 
	               two_x_0 / 2 + 2, two_y_0 / 2 + i * dlines);
	    g.drawLine(two_x_0 / 2, two_y_0 / 2 - i * dlines, 
	               two_x_0 / 2 + 2, two_y_0 / 2 - i * dlines);
    }
    for (int i = 1; i <= vlines / 2 +1; i++) {
        g.drawLine(two_x_0 / 2 + i * dlines, two_y_0 / 2 , 
                   two_x_0 / 2 +  i * dlines, two_y_0 / 2 - 2);
	    g.drawLine(two_x_0 / 2 - i * dlines, two_y_0 / 2 , 
	               two_x_0 / 2 -  i * dlines, two_y_0 / 2 - 2);
    }
    g.setColor(Color.darkGray);
    for (int i = 1; i <= hlines / dlines +3; i++) {
	    g.drawString(""+i,two_x_0/2 - 12,two_y_0 / 2 - i * dlines );   
    }

    for (int i = 1; i <= vlines / dlines +4; i++) {
	    g.drawString(""+(i + nxxoff),two_x_0 / 2 + i * dlines, two_y_0/2 - 3);   	   
    }

/*
 * Draw data for Mohr's circle and stresses onto the window
 */ 
	    g.setColor(Color.darkGray);
	    g.drawString("sigma x " + dunit ,two_x_0 - 105, two_y_0 / 2 + 12 );
	    g.drawString("tau x " + dunit ,two_x_0/2 + 6, 12 );	    
	    g.drawString("O(" + nxxoff + ",0)",two_x_0/2 + 6,two_y_0 / 2 + 12 );	    	    

	    g.setColor(Color.white);
	    g.drawString("Input Stresses:",10,12);
	    g.drawString("sigma_x = " + dsigma_x,10,27);
	    g.drawString("sigma_y = " + dsigma_y,10,42);
	    g.drawString("tau_xy = " + dtau_xy,10,57);	

	    g.setColor(Color.blue);
	    g.drawString("Mohr's Circle: ",10,87);
	    g.drawString("sigma_ave = " + dsigma_ave,10,102);
	    g.drawString("radius = " + dradius,10,117);

	    g.drawString("Principal Stresses:",10,two_y_0 / 2 + 12);
	    g.drawString("sigma_1 = " + dsigma_1,10,two_y_0 / 2 + 27);
	    g.drawString("sigma_2 = " + dsigma_2,10,two_y_0 / 2 + 42);
	    g.drawString("theta_p = " + dtheta_p + " deg.",10,two_y_0 / 2 + 57);
	    g.drawString("sigma_mises = " + dsigma_mis,10,two_y_0 / 2 + 72);
	    g.drawString("tau_max = " + dradius,10,two_y_0 / 2 + 87);	

	    g.setColor(Color.blue);	    
	    g.drawString(" sigma_1 ",two_x_0/2 + xx +radius,two_y_0 - 33);
	    g.drawLine(two_x_0 / 2 + xx + radius, two_y_0 - 33, 
	               two_x_0 / 2 + xx + radius, two_y_0/ 2);
	    g.drawString(" sigma_2",two_x_0/2 + xx -radius,two_y_0 - 3 );	        
	    g.drawLine(two_x_0 / 2 + xx - radius, two_y_0 - 3 , 
	               two_x_0 / 2 + xx - radius, two_y_0 / 2);
	    g.drawString("tau_max",two_x_0/2 - 150, two_y_0/2 - radius - 3);
	    g.drawLine(two_x_0 / 2 - 150, two_y_0 / 2 - radius , 
	               two_x_0 / 2 + xx, two_y_0 / 2 - radius);
	    g.drawString(" sigma_ave ",two_x_0/2 + xx,two_y_0 - 18);
	    g.drawLine(two_x_0 / 2 + xx, two_y_0 - 18, 
	               two_x_0 / 2 + xx, two_y_0 / 2);

	    g.setColor(Color.white);	   	    
	    if(sxx <= syy) {
	       g.drawString(" sigma_x",two_x_0/2 + sxx, two_y_0 - 48);
	       g.drawLine(two_x_0 / 2 + sxx, two_y_0 - 48, 
	                  two_x_0 / 2 + sxx, two_y_0 / 2 - txy);
	       g.drawString(" sigma_y",two_x_0/2 + syy,two_y_0 - 63);
	       g.drawLine(two_x_0 / 2 + syy, two_y_0 - 63, 
	                  two_x_0 / 2 + syy, two_y_0 / 2 - txy);
	       g.drawString("tau_xy ",two_x_0/2 - 90, two_y_0/2 - txy -3);	                 	    
	       g.drawLine(two_x_0 / 2  - 90, two_y_0/2 - txy , 
	                  two_x_0 / 2 + sxx, two_y_0 / 2 - txy);
	    } else {
	           g.drawString(" sigma_x",two_x_0/2 + sxx, two_y_0 - 63);
	           g.drawLine(two_x_0 / 2 + sxx, two_y_0 - 63, 
	                      two_x_0 / 2 + sxx, two_y_0 / 2 - txy);  
	           g.drawString(" sigma_y",two_x_0/2 + syy,two_y_0 - 48);
	           g.drawLine(two_x_0 / 2 + syy, two_y_0 - 48, 
	                      two_x_0 / 2 + syy, two_y_0 / 2 - txy);
	           g.drawString("tau_xy ",two_x_0/2 - 90, two_y_0/2 - txy -3);	                 	    
	           g.drawLine(two_x_0 / 2  - 90, two_y_0/2 - txy , 
	                      two_x_0 / 2 + syy, two_y_0/2 - txy);
	      } 
        g.drawLine(two_x_0 / 2 + sxx, two_y_0/2 - txy , 
                   two_x_0 / 2 + syy, two_y_0/2 - txy);



        double sigma = (double)((int)(100.0d * (double)(xp - two_x_0/2)/(double)dlines)) / 100.0d;
        double tau   = (double)((int)(100.0d * (double)(two_y_0/2 - yp)/(double)dlines)) / 100.0d;

        g.setColor(Color.red);
        g.drawString("sigma = " + (dunit * (sigma + nxxoff)),two_x_0 - 115, 12); 
        g.drawString("tau = " + (dunit * tau) ,two_x_0 - 115, 27);                      
        g.setColor(Color.green);
        g.drawString("The green sector has", 10, two_y_0 - 27);                      
        g.drawString("an angle of 2 times theta_p.", 10, two_y_0 - 12);                                                            

    }

    public void redraw(String filled,
                       int xp,
                       int yp,
	  	               double dsigma_x,	    
	                   double dsigma_y,
                       double dtau_xy,                       
                       double dradius, 
                       double dsigma_ave, 
                       double dsigma_1,
                       double dsigma_2, 
                       double dtheta_p,
                       double dsigma_mis) {
	                   this.filled = filled;
	                   this.xp = xp;
	                   this.yp = yp;
	                   this.dsigma_x = dsigma_x;
	                   this.dsigma_y = dsigma_y;
	                   this.dtau_xy = dtau_xy;	                   	                   
                       this.dradius = dradius;
	                   this.dsigma_ave = dsigma_ave;
                       this.dsigma_1 = dsigma_1;
                       this.dsigma_2 = dsigma_2;
                       this.dtheta_p = dtheta_p;
                       this.dsigma_mis = dsigma_mis;  
	                   repaint();
    }

    public boolean mouseDown(Event evt, int x, int y){ 
    	     
      Rectangle r = bounds();
      if(x < r.width) { if ( y < r.height) {
        xp = x;
        yp = y;
	    redraw(filled,
	                  xp,
	                  yp,
	  	              dsigma_x,	    
	                  dsigma_y,
                      dtau_xy,
                      dradius, 
                      dsigma_ave, 
                      dsigma_1,
                      dsigma_2, 
                      dtheta_p,
                      dsigma_mis);

         return true;       
                         }                    
      } 
    return true;   
    }    
        
}

class MohrControls extends Panel {
    TextField sigma_xText;
    TextField sigma_yText;
    TextField tau_xyText;
    MohrCanvas canvas;

        int xp = 0;
        int yp = 0;
	  	double  dsigma_x;	    
	    double  dsigma_y;
        double  dtau_xy;
        double  dradius;
        double  dsigma_ave;	    
	    double  dsigma_1;
        double  dsigma_2;        
        double  dtheta_p;
        double  dsigma_mis;     

    public MohrControls(MohrCanvas canvas) {
	this.canvas = canvas;
    setLayout(new GridLayout(2,7,5,0));   
    add(sigma_xText = new TextField("0.0", 8));
	add(sigma_yText = new TextField("0.0", 8));
	add(tau_xyText = new TextField("0.0", 8));
	add(new Button("Fill"));
	add(new Button("Draw"));
    add(new Button("size 1"));
	add(new Button("size 2"));	
	add(new Label(" sigma_x"));	
	add(new Label(" sigma_y"));		
	add(new Label("  tau_xy"));
	add(new Label(""));				
	add(new Label(""));
	add(new Label("  2 times"));		
	add(new Label("  4 times"));					
    }

    public boolean action(Event ev, Object arg) {
	if (ev.target instanceof Button) {
   
/*
 * Get the original stresses for a Mohr's circle 
 */        
        dsigma_x = (Double.valueOf(sigma_xText.getText().trim())).doubleValue();
        dsigma_y = (Double.valueOf(sigma_yText.getText().trim())).doubleValue();
        dtau_xy = (Double.valueOf(tau_xyText.getText().trim())).doubleValue();
/*
 * Calculate the data for Mohr's circle and principal stresses
 */         
        dradius = Math.sqrt((dsigma_x - dsigma_y) * (dsigma_x - dsigma_y)/4.0d 
                + dtau_xy * dtau_xy);
        dsigma_ave = (dsigma_x + dsigma_y)/2.0d;
        dsigma_1 = dsigma_ave + dradius;
        dsigma_2 = dsigma_ave - dradius;
        dtheta_p = (90.0d/Math.PI)*Math.atan(2.0d*dtau_xy/(dsigma_x - dsigma_y));  
        dsigma_mis = Math.sqrt(dsigma_x * dsigma_x - 
                               dsigma_x * dsigma_y + 
                               dsigma_y * dsigma_y + 
                               3.0d * dtau_xy * dtau_xy);

/*
 * Draw Mohr's circle and principal stresses onto the window
 */         

	    canvas.redraw((String)arg,
	                  xp,
	                  yp,
	  	              dsigma_x,	    
	                  dsigma_y,
                      dtau_xy,
                      dradius, 
                      dsigma_ave, 
                      dsigma_1,
                      dsigma_2, 
                      dtheta_p,
                      dsigma_mis);	    

	    return true;
	}
	return false;
    }
}
