Tutorial: Drawing Basic Logic Gates with GWT

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 18:21, 4 July 2014 (EDT)



GoogleWebKitLogo.png



GWT Tutorials



This recipe illustrates how to draw logic gates on a GWT canvas. I found remarkably little information on the Web about the geometry and the generation of logic gates, including the OR gate and its 3 arcs, and decided to just create the 3 basic gates: AND, INVERTER, and OR. The NAND and NOR gates can easily be generated from the information presented here. Look at other GWT Tutorials in this Wiki for information about setting up Eclipse and generating simple GWT Web applications.


Setup


  • Mac OSX 10.8.5 with Java SDK 1.7
  • Eclipse Kepler
  • Google WebKit gwt-6.2.1.


Sample Output


This is what we're after, below: a way to generate simple AND, OR, and INVERTER gates on a GWT canvas.

GWTLogicGatesOnCanvas.png


Gate Geometry


The geometry for the gates is given by an IEEE document, with this main illustration, shown below, and found in Chapter 9 of this on-line reference on ASICS: http://iroi.seu.edu.cn/books/asics/ASICs.htm. (The OR gate shape is better spotted in the other diagram, located toward the end of this page.)

GateGeometryIEEE.gif


The Java Project


Canvas3.java


/*
 * Canvas3.java
 * D. Thiebaut
 * A simple canvas application that positions a few gates in a 800x600 canvas.
 */

package dft.client;

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * The main class for the project.  Implements an empty canvas (Context2D) on which
 * a few gates are drawn, along with 3 text labels
 */
public class Canvas3 implements EntryPoint {
    Canvas canvas;
    Context2d context;
    static final int canvasHeight = 800;
    static final int canvasWidth = 600;
     
    public void onModuleLoad() {         
        canvas = Canvas.createIfSupported();
         
        if (canvas == null) {
              RootPanel.get().add(new Label("Sorry, your browser doesn't support the HTML5 Canvas element"));
              return;
        }
         
        // standard code to size the canvas 
        canvas.setStyleName("mainCanvas");      
        canvas.setWidth(canvasWidth + "px");
        canvas.setCoordinateSpaceWidth(canvasWidth);
         
        canvas.setHeight(canvasHeight + "px");      
        canvas.setCoordinateSpaceHeight(canvasHeight);
         
        RootPanel.get().add(canvas);
        context = canvas.getContext2d();
         
        // drop a few gates on the canvas         
        for ( int x = 100; x < 300; x += 75 ) {

                // some inverters facing right
        	InverterRight inv = new InverterRight( context, x, 300 );
        	inv.draw();

                // some inverters facing down 
        	InverterDown inv2 = new InverterDown( context, 300, x );
        	inv2.draw();

                // some AND gates (facing right)
        	AndGate a = new AndGate( context, x+50, 150 );
        	a.draw();

        }
        
        // an OR gate         
        OrGate or1 = new OrGate( context, 200, 200 );
        or1.draw();
        
        // Put some labels
        TextLabel L1, L2, L3;
        L1 = new TextLabel( context, "75-75", 75, 75);
        L1.draw();
        L2 = new TextLabel( context, "195-95", 195, 95);
        L2.draw();
        L3 = new TextLabel( context, "75-195", 75, 195);
        //L3.setFont( "bold 22px sans-serif");
        L3.draw();
    }
     
}

AndGate.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class AndGate {

	Context2d context;
	double x;
	double y;
	double andGateHeight = 30;
    double andGateLength = 40;

    double xin1, yin1, xin2, yin2, xout, yout;
    
	public AndGate( Context2d c, double xx, double yy ) {
		x = xx;
		y = yy;
		context = c;
		xin1 = x;
		xin2 = x;
		yin1 = y + andGateHeight/4;
		yin2 = y + 3*andGateHeight/4;
		xout = x + andGateLength/3 + andGateHeight/2;
		yout = y + andGateHeight/2;
	}
	
	public void draw() {        
        context.moveTo( x,  y );
        context.lineTo( x, y+andGateHeight );
        context.lineTo( x+andGateLength/3, y+andGateHeight );
        context.moveTo( x,  y );
        context.lineTo( x+andGateLength/3, y );
        context.stroke();
        
        context.moveTo( x+andGateLength/3, y );
        context.arc( x+andGateLength/3 , y+andGateHeight/2, andGateHeight/2, -Math.PI/2, Math.PI/2);
        context.stroke();
	}
	
	public void drawIO() {
		context.moveTo( xin1, yin1);
		context.arc( xin1, yin1, 2, 0, Math.PI*2 );
		context.stroke();
		
		context.moveTo( xin2, yin2);
		context.arc( xin2, yin2, 2, 0, Math.PI*2 );
		context.stroke();
		
		context.moveTo( xout, yout);
		context.arc( xout, yout, 2, 0, Math.PI*2 );
		context.stroke();
	}
}


InverterDown.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class InverterDown {
	double x;
	double y;
	double xin, yin, xout, yout;

	Context2d context = null;
	int inverterHeight = 20;
	int inverterLength = 20;
	int inverterCircleRadius = 5;
	int calculatedCenterx = 0;
	int calculatedCentery = inverterHeight + inverterCircleRadius;

	public InverterDown(Context2d c, double xx, double yy) {
		context = c;
		x = xx;
		y = yy;

		xin = x;
		yin = y;
		yout = y + inverterLength + inverterCircleRadius * 2;
		xout = x;

	}

	public void draw() {
		context.moveTo(x, y);
		context.lineTo(x - inverterHeight / 2, y);
		context.lineTo(x, y + inverterLength);
		context.lineTo(x + inverterHeight / 2, y);
		context.lineTo(x, y);
		context.stroke();

		context.moveTo(x + calculatedCenterx + inverterCircleRadius, y
				+ calculatedCentery);
		context.arc(x + calculatedCenterx, y + calculatedCentery,
				inverterCircleRadius, 0, Math.PI * 2.0, true);
		context.stroke();

	}

	public void drawIO() {
		context.moveTo(xin, yin);
		context.arc(xin, yin, 2, 0, Math.PI * 2);
		context.stroke();

		context.moveTo(xout, yout);
		context.arc(xout, yout, 2, 0, Math.PI * 2);
		context.stroke();
	}

}

InverterRight.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class InverterRight {
	double x;
	double y;
	double xin, yin, xout, yout;

	Context2d context = null;
	int inverterHeight = 20;
	int inverterLength = 20;
	int inverterCircleRadius = 5;
	int calculatedCenterx = inverterLength + inverterCircleRadius;
	int calculatedCentery = 0;

	public InverterRight(Context2d c, double xx, double yy) {
		context = c;
		x = xx;
		y = yy;
		xin = x;
		yin = y;
		xout = x + inverterLength + inverterCircleRadius * 2;
		yout = y;
	}

	public void draw() {
		context.moveTo(x, y);
		context.lineTo(x, y - inverterHeight / 2);
		context.lineTo(x + inverterLength, y);
		context.lineTo(x, y + inverterHeight / 2);
		context.lineTo(x, y);
		context.stroke();
		context.moveTo(x + calculatedCenterx + inverterCircleRadius, y
				+ calculatedCentery);
		context.arc(x + calculatedCenterx, y + calculatedCentery,
				inverterCircleRadius, 0, Math.PI * 2.0, true);
		context.stroke();
	}

	public void drawIO() {
		context.moveTo(xin, yin);
		context.arc(xin, yin, 2, 0, Math.PI * 2);
		context.stroke();

		context.moveTo(xout, yout);
		context.arc(xout, yout, 2, 0, Math.PI * 2);
		context.stroke();
	}
}

OrGate.java


The geometry of the OR gate is better illustrated by labeling key points in the original diagram. These (x,y) points are computed in the java code below. All the angles considered are PI/6 for the gate itself. To locate the two inputs of the gate, we use + and -PI/12 from the x6,y6 center of the left circle.

ORGateGeometryAndLabels.png


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

/**
 * OrGate
 * 
 * @author thiebaut
 * 
 *         Defined by geometry of IEEE pub:
 *         http://iroi.seu.edu.cn/books/asics/Book/CH09/CH09-1.gif
 */
public class OrGate {

	// various points defining the gate
	Context2d context;
	double x, x1, x2, x3, x4, x5, x6;
	double y, y1, y2, y3, y4, y5, y6;

	double radius = 26;
	double height = 26;
	double flat = 10;
	double alpha, beta;

	// inputs and output
	double xin1, yin1, xin2, yin2, xout, yout;

	public OrGate(Context2d c, double xx, double yy) {
		x = xx;
		y = yy;
		context = c;

		// compute various quantities
		alpha = Math.PI / 6;
		beta = alpha;
		y1 = y - radius / 2;
		y2 = y1;
		y3 = y;
		y4 = y2 + height;
		y5 = y4;
		y6 = y;

		x6 = x - flat - radius;
		x1 = x6 + radius * Math.sqrt(3) / 2;
		x5 = x1;
		x2 = x;
		x4 = x;
		x3 = x + radius * Math.sqrt(3) / 2;

		// I/O Pins
		xin1 = x6 + radius * 0.96592582628; // cos( PI/12 )
		yin1 = y - radius * 0.2588190451; // sin( PI/12 )

		xin2 = xin1;
		yin2 = y + radius * 0.2588190451; // sin( PI/12 )

		xout = x3;
		yout = y3;
	}

	public double getXInput1() {
		return xin1;
	}

	public double getYInput1() {
		return yin1;
	}

	public double getXInput2() {
		return xin2;
	}

	public double getYInput2() {
		return yin2;
	}

	public double getXOutput() {
		return xout;
	}

	public double getYOutput() {
		return yout;
	}

	public void draw() {

		// draw 1-2
		context.moveTo(x1, y1);
		context.lineTo(x2, y2);
		context.stroke();

		// draw 2-3
		context.moveTo(x2, y2);
		context.arc(x4, y4, radius, 3 * Math.PI / 2, Math.PI * 2 - Math.PI / 6);
		context.stroke();

		// draw 4-3
		context.moveTo(x3, y3);
		context.arc(x2, y2, radius, Math.PI / 6, Math.PI / 2);
		context.stroke();

		// Draw 4-5
		context.moveTo(x4, y4);
		context.lineTo(x5, y5);
		context.stroke();

		// Draw 1-5
		context.moveTo(x1, y1);
		context.arc(x6, y6, radius, -Math.PI / 6, Math.PI / 6);
		context.stroke();
	}
}

TextLabel.java


package dft.client;

import com.google.gwt.canvas.dom.client.Context2d;

public class TextLabel {

	Context2d context;
	String text;
	double x, y;
	String font = "bold 22px sans-serif";
	
	public TextLabel( Context2d c, String t, double xx, double yy ) {
			context = c;
			text = t;
			x = xx;
			y = yy;
	}
	
	public void setFont( String f ) {
		font = f;
	}
	
	public void draw() {
		context.setFont( font );
		context.fillText( text, x, y);
	}
}