package dwarf.gfx;
import java.util.Objects;
import dwarf.GameObject;
import dwarf.util.Point2D;
import dwarf.DwarfException;
/**
* A basic figure made up of 3 or more sides/edges and 3 or more
* vertices/corners.
*
* @author Matthew 'siD' Van der Bijl
*
* @see <a href='http://en.wikipedia.org/wiki/Polygon'>wikipedia</a>
* @see dwarf.GameObject
* @see dwarf.Collidable
* @see dwarf.gfx.draw
* @see dwarf.gfx.shapeConstants
* @see dwarf.gfx.Colours
*/
@SuppressWarnings("serial")
public class Polygon extends dwarf.Collidable implements GameObject, shapeConstants, Colours {
public final static int FILL = 0x0;
public final static int STROKE = 0x1;
/**
* the colour of the <code>Polygon</code>.
*/
private Colour colour;
/**
* the mode of the <code>Polygon</code>. (stroke/fill)
*/
private byte mode;
private boolean update;
private boolean render;
/**
* Default constructor.
*/
public Polygon() {
super();
}
/**
* Constructs a new <code>Polygon</code> with no vertices.
*
* @param position the position of the <code>Polygon</code> on the screen
* @param mode the mode of the <code>Polygon</code> to be created
* @param colour the <code>Colour</code> of the <code>Polygon</code> to be
* created
*/
public Polygon(Point2D position, int mode, Colour colour) {
super(position);
this.update = true;
this.render = true;
this.setMode(mode);
this.colour = colour;
}
/**
* Constructs a new <code>Polygon</code> with no vertices.
*
* @param vertices the vertices of the <code>Polygon</code> to be created
* @param position the position of the <code>Polygon</code> on the screen
* @param mode the mode of the <code>Polygon</code> to be created
* @param colour the <code>Colour</code> of the <code>Polygon</code> to be
* created
*/
public Polygon(Point2D[] vertices, Point2D position, int mode, Colour colour) {
super(position, null);
this.update = true;
this.render = true;
this.setMode(mode);
this.colour = colour;
super.setVertices(vertices);
}
public Polygon(Polygon polygon) {
super(polygon.getPosition(), null);
this.update = true;
this.render = true;
this.setMode(polygon.getMode());
this.colour = polygon.getColour();
super.setVertices(polygon.getVertices());
}
/**
* Callback function used to update the state of the game every frame.
*/
@Override
public void update() {
}
/**
* Callback function used to render the <code>Polygon</code> to the screen.
*
* @see dwarf.gfx.draw#fillPolygon(dwarf.util.Point2D[], dwarf.util.Point2D,
* double, dwarf.gfx.Colour)
* @see dwarf.gfx.draw#strokePolygon(dwarf.util.Point2D[],
* dwarf.util.Point2D, double, dwarf.gfx.Colour)
*/
@Override
public void render() {
if (getRender()) {
if (isFill()) {
draw.fillPolygon(super.getVertices(), super.getPosition(), 0, this.getColour());
} else {
draw.strokePolygon(super.getVertices(), super.getPosition(), 0, this.getColour());
}
}
}
/**
* @return true if the Polygon's mode is equal to Fill and if stroke will
* return false
*/
public boolean isFill() {
return this.getMode() == FILL;
}
/**
* @return true if the Polygon's mode is equal to stroke and if fill will
* return false
*/
public boolean isStroke() {
return !isFill();
}
public Colour getColour() {
return this.colour;
}
public void setColour(Colour colour) {
this.colour = colour;
}
/**
* This method is called from within the constructor to initialize the
* <code>Polygon</code>. <b>WARNING: Do NOT modify this code.</b>
*
* @throws DwarfException it the inputed mode in not recognised
* @param mode the mode of the <code>Polygon</code>
*/
public final void setMode(int mode) throws DwarfException {
if ((byte) mode == FILL || (byte) mode == STROKE) {
this.mode = (byte) mode;
} else {
throw new DwarfException("illegal argument");
}
}
/**
* 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 = 3;
hash = 47 * hash + Objects.hashCode(mode);
hash = 47 * hash + Objects.hashCode(colour);
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 Polygon other = (Polygon) obj;
if (!Objects.equals(this.getColour(), other.getColour())) {
return false;
} else if (Objects.equals(this.getMode(), other.getMode())) {
return false;
}
return true;
}
public int getMode() {
return this.mode;
}
/**
* Returns what type of shape <code>this</code> is.
*
* @see dwarf.gfx.shapeConstants
*
* @return what type of shape <code>this</code> is
*/
public String getType() {
switch (super.getNumVertices()) {
case SHAPE_TRIANGLE:
return "triangle";
case SHAPE_SQUARE:
return "quadrilateral";
case SHAPE_PENTAGON:
return "pentagon";
case SHAPE_HEXAGON:
return "hexagon";
case SHAPE_HEPTAGON:
return "heptagon";
case SHAPE_OCTAGON:
return "octagon";
case SHAPE_NONAGON:
return "nonagon";
case SHAPE_DECAGON:
return "decagon";
case SHAPE_HENDECAGON:
return "hendecagon";
case SHAPE_DODECAGON:
return "dodecagon";
case SHAPE_TRISKAIDECAGON:
return "tridecagon";
case SHAPE_TETRAKAIDECAGON:
return "tetradecagon";
case SHAPE_PENTAKAIDECAGON:
return "pentadecagon";
case SHAPE_HEXAKAIDECAGON:
return "hexadecagon";
case SHAPE_HEPTAKAIDECAGON:
return "heptakaidecagon";
case SHAPE_OCTAKAIDECAGON:
return "octadecagon";
case SHAPE_ENNEAKAIDECAGON:
return "enneadecagon";
case SHAPE_ICOSAGON:
return "icosagon";
case SHAPE_ICOSIKAIHEXAGON:
return "icosikaihexagon";
case SHAPE_ICOSIKAITRIGON:
return "icosikaitetragon";
case SHAPE_ICOSIKAITETRAGON:
return "icosikaitetragon";
case SHAPE_CIRCLE:
return "circle";
default:
return "polygon";
}
}
@Override
public Polygon get() {
return this;
}
public void set(Point2D[] vertices, Point2D position, int mode, Colour colour) {
this.update = true;
this.render = true;
this.setMode(mode);
this.colour = colour;
super.setVertices(vertices);
super.setPosition(position);
}
public void set(Polygon polygon) {
this.setMode(polygon.getMode());
this.colour = polygon.getColour();
super.setVertices(polygon.getVertices());
super.setPosition(polygon.getPosition());
}
@Override
public Polygon clone() throws CloneNotSupportedException {
return new Polygon(this);
}
public double getPerimeter() {
double result = Point2D.distance(getVertices()[0], getVertices()[getNumVertices() - 1]);
for (int i = 0; i < getNumVertices(); i++) {
try {
result += Point2D.distance(getVertices()[i], getVertices()[i + 1]);
} catch (ArrayIndexOutOfBoundsException outOfBoundsException) {
break;
}
}
return result;
}
public boolean getRender() {
return this.render;
}
public void setRender(boolean render) {
this.render = render;
}
public boolean getUpdate() {
return this.update;
}
public void setUpdate(boolean update) {
this.update = update;
}
//TODO
/**
* TODO, A cyclic quadrilateral is a four-sided figure with all four
* vertices lying on the circumference of a circle.
*
* @return true if this is a cyclic quad
*/
public boolean isCyclicQuad() {
//if this is a rectangle it will be a cyclic quad.
if (this.isRectangle()) {
return true;
} else {
return false;
}
}
public boolean isRectangle() {
if (this.getType().equals("quadrilateral")) {
dwarf.util.Line[] sides = {
new dwarf.util.Line(super.getVertices()[0], super.getVertices()[1]),
new dwarf.util.Line(super.getVertices()[1], super.getVertices()[2]),
new dwarf.util.Line(super.getVertices()[2], super.getVertices()[3]),
new dwarf.util.Line(super.getVertices()[3], super.getVertices()[0])
};
return sides[0].length() == sides[1].length() && sides[1].length() == sides[3].length();
} else {
return false;
}
}
public boolean isSquare() {
if (this.getType().equals("quadrilateral")) {
dwarf.util.Line[] sides = {
new dwarf.util.Line(super.getVertices()[0], super.getVertices()[1]),
new dwarf.util.Line(super.getVertices()[1], super.getVertices()[2]),
new dwarf.util.Line(super.getVertices()[2], super.getVertices()[3]),
new dwarf.util.Line(super.getVertices()[3], super.getVertices()[0])
};
if (sides[0].length() != sides[3].length()) {
return false;
} else {
for (int i = 0; i < sides.length; i++) {
try {
if (sides[i].length() != sides[i + 1].length()) {
return false;
}
} catch (ArrayIndexOutOfBoundsException outOfBoundsException) {
break;
}
}
}
return true;
} else {
return false;
}
}
/**
* 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 "Polygon[" + "colour: " + colour + ", mode: " + mode
+ ", update: " + update + ", render: " + render + "]";
}
}