NamedShape.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ostrichemulators.semtool.om;

import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;

/**
 *
 * @author ryan
 */
public enum NamedShape {

	CIRCLE( 0 ), SQUARE( -1 ), STAR3( 3, true ), DIAMOND( 4 ), STAR5( 5, true ),
	HEXAGON( 6 ), STAR6( 6, true ), PENTAGON( 5 ), TRIANGLE( 3 ), STAR4( 4, true ),
	URCHIN( 9, true );

	int points;
	boolean star;

	NamedShape( int points, boolean star ) {
		this.star = star;
		this.points = points;
	}

	NamedShape( int points ) {
		this( points, false );
	}

	public boolean isStar() {
		return star;
	}

	public boolean isSquare() {
		return points < 0;
	}

	public int numPoints() {
		return points;
	}

	public Shape getShape( double size ) {
		if ( star ) {
			return createStar( size, points );
		}
		else if ( isSquare() ) {
			// the square looks too big compared to the other shapes, so make it a little smaller
			return new Rectangle2D.Double( 2, 2, size - 4, size - 4 );
		}
		else if ( 0 == points ) {
			return new Ellipse2D.Double( 0, 0, size, size );
		}
		else {
			return createPolygon( size, points );
		}
	}

	/**
	 * Creates a star shape
	 * @param size how big to make the star
	 * @param points how many points does it have?
	 * @return a star
	 */
	public static Shape createStar( double size, int points ) {
		// we're (imagining) drawing two concentric circles
		// and walking around both, while putting points.
		// then just connect the inner points to the outer ones,
		// and we have our star
		//Ellipse2D outer = new Ellipse2D.Double( 0, 0, size, size );
		//Ellipse2D inner = new Ellipse2D.Double( size / 3, size / 3, size / 3, size / 3 );

		final double center = size / 2;
		final double outerRadius = size / 2;
		final double innerRadius = size / 4;
		final double pointAngle = 360 / points;

		double x[] = new double[points * 2];
		double y[] = new double[points * 2];

		GeneralPath star = new GeneralPath();
		// star.append( outer, false );
		// star.append( inner, false );
		double offset = Math.PI / 2;

		for ( int i = 0; i < points; i++ ) {
			double innerDegree = ( Math.toRadians( i - 0.5 ) * pointAngle ) - offset;
			double innerX = innerRadius * Math.cos( innerDegree ) + center;
			double innerY = innerRadius * Math.sin( innerDegree ) + center;

			double outerDegree = ( Math.toRadians( i ) * pointAngle ) - offset;
			double outerX = outerRadius * Math.cos( outerDegree ) + center;
			double outerY = outerRadius * Math.sin( outerDegree ) + center;

			int pos = 2 * i;
			x[pos] = innerX;
			y[pos] = innerY;
			x[pos + 1] = outerX;
			y[pos + 1] = outerY;

			//star.append( new Ellipse2D.Double( x[pos], y[pos], 1, 1 ), false );
			//star.append( new Ellipse2D.Double( x[pos + 1], y[pos + 1], 1, 1 ), false );
		}

		star.moveTo( x[0], y[0] );
		for ( int i = 1; i < x.length; i++ ) {
			star.lineTo( x[i], y[i] );
		}
		star.closePath();
		return star;
	}

	public static Shape createPolygon( double size, int points ) {
		// we're (imagining) drawing a circle, and walking aroun
		// walking around it while putting points.
		// Ellipse2D outer = new Ellipse2D.Double( 0, 0, size, size );

		final double center = size / 2;
		final double radius = size / 2;
		final double pointAngle = 360 / points;

		double x[] = new double[points];
		double y[] = new double[points];

		GeneralPath poly = new GeneralPath();
			// poly.append( outer, false );

		// back up our points by 90% so the shapes "point" up instead of to the right
		double offset = Math.PI / 2;

		for ( int i = 0; i < points; i++ ) {
			double outerDegree = ( Math.toRadians( i ) * pointAngle ) - offset;
			double outerX = radius * Math.cos( outerDegree ) + center;
			double outerY = radius * Math.sin( outerDegree ) + center;

			x[i] = outerX;
			y[i] = outerY;

			//poly.append( new Ellipse2D.Double( x[i], y[i], 1, 1 ), false );
		}

		poly.moveTo( x[0], y[0] );
		for ( int i = 1; i < x.length; i++ ) {
			poly.lineTo( x[i], y[i] );
		}
		poly.closePath();
		return poly;
	}
};