package dwarf.gfx; import dwarf.util.math; import dwarf.util.Point2D; import dwarf.util.Vector2; import dwarf.DwarfException; import static dwarf.util.math.sin; import static java.lang.Math.abs; import static java.lang.Math.tan; /** * A regular figure that has sides, edges and angles that are congruent. * * @author Matthew 'siD' Van der Bijl * * @see dwarf.gfx.Polygon */ public class Shape extends Polygon { private byte numSides; private double lineLength; /** * Default constructor. */ public Shape() { super(); } public Shape(int numSides, double lineLength, Point2D position, int mode, Colour colour) { super(position, mode, colour); numSides = abs(numSides); if (numSides >= 3) { if (numSides >= 60) { numSides = 60; } this.numSides = (byte) numSides; this.lineLength = lineLength; this.init(); } else { throw new DwarfException("illegal argument"); } } public Shape(Shape shape) { super(shape.getPosition(), shape.getMode(), shape.getColour()); this.numSides = (byte) shape.getNumSides(); this.lineLength = shape.getLineLength(); this.init(); } /** * This method is called from within the constructor to initialize the * <code>Shape</code>. <b>WARNING: Do NOT modify this code.</b> */ protected final void init() { Point2D[] point = new Point2D[numSides]; Vector2 temp = new Vector2(); int angle = 360 / numSides; for (int i = 0; i < numSides; i++) { temp.move(getLineLength()); temp.rotate(angle); point[i] = new Point2D(temp.getX(), (temp.getY())); } super.setVertices(point); } public int getNumSides() { return this.numSides; } public void setNumSides(int numSides) { this.numSides = (byte) numSides; } public double getLineLength() { return this.lineLength; } public void setLineLength(double lineLength) { this.lineLength = lineLength; } @Override public double getPerimeter() { return (getNumSides() * getLineLength()); } public void changeNumSides(int input) { this.numSides += input; } /** * The apothem is also the radius of the encircle of the polygon. For a * polygon of n sides, there are n possible apothem, all the same length of * course. The word apothem can refer to the line itself, or the length of * that line. * * @return 5 / (2 * tan(180 / numSides)) */ public double getApothem() { return 5 / (2 * tan(180 / getNumSides())); } public double getRadius() { return 5 / (2 * (sin(180 / getNumSides()))); } /** * Class Object is the root of the class hierarchy. Every class has Object * as a superclass. All objects, including arrays, implement the methods of * this class. * * @return a hash code value for this object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public int hashCode() { int hash = 5; hash = 13 * hash + getNumSides(); hash = 13 * hash + (int) (Double.doubleToLongBits(getLineLength()) ^ (Double.doubleToLongBits(getLineLength()) >>> 32)); return hash; } /** * Returns true if the <code>this</code> is equal to the argument and false * otherwise. Consequently, if both argument are null, true is returned, * false is returned. Otherwise, equality is determined by using the equals * method of the first argument. * * @param obj the <code>Object</code> to be tested * @see java.lang.Object#equals(java.lang.Object) * * @return true if the argument is equal to <code>this</code> other and * false otherwise */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } else if (getClass() != obj.getClass()) { return false; } else if (!super.equals(obj)) { return false; } final Shape other = (Shape) obj; if (this.getNumSides() != other.getNumSides()) { return false; } else if (Double.doubleToLongBits(getLineLength()) != Double.doubleToLongBits(other.getLineLength())) { return false; } return true; } /** * calculates the area of any regular polygon using the length of each line * segment and the number of line segments. Rounds off to three decimal * places. * * @author Shane Acton * @author Isa Cattanach * @author Matthew Van der Bijl * * @return returns the area of the <code>Shape</code> (double) */ public double getArea() { return (Math.round((math.sqr(getLineLength() / 2) * Math.tan(Math.toRadians(180 - (360 / getNumSides())) / 2)) * getNumSides()) * 1000) / 1000; } @Override public Shape get() { return this; } public void scale(double delta) { this.setLineLength(getLineLength() * delta); } @Override @Deprecated public void addPoint(Point2D point) { super.addPoint(point); } @Override public Shape clone() throws CloneNotSupportedException { return new Shape(this); } @Override @Deprecated public void addPoints(Point2D[] points) { super.addPoints(points); } @Override @Deprecated public void addPoint(double xPos, double yPos) { super.addPoint(xPos, yPos); } @Override @Deprecated public void setVertices(double[] xPoints, double[] yPoints) { super.setVertices(xPoints, yPoints); } @Override @Deprecated public void setVertices(java.awt.Polygon p) { super.setVertices(p); } @Override @Deprecated public void setVertices(Point2D[] vertices) { super.setVertices(vertices); } /** * Returns a string representation of the object. * <p> * In general, the toString method returns a string that "textually * represents" this object. The result should be a concise but informative * representation that is easy for a person to read. It is recommended that * all subclasses override this method.</p> * * @return a textually representation of this object */ @Override public String toString() { return "Shape[" + "numSides: " + numSides + ", lineLength: " + lineLength + "]"; } }