// --------------------------------------------------- // imports // --------------------------------------------------- import java.awt.BasicStroke; import java.awt.Graphics2D; import java.awt.Color; // --------------------------------------------------- // Square // --------------------------------------------------- public class Square { // --------------------------------------------------- // Square - Construct s Square from four (x, y) pairs // of points // --------------------------------------------------- public Square(XY p1, XY p2, XY p3, XY p4) { mP1 = p1; mP2 = p2; mP3 = p3; mP4 = p4; mSize = p1.distance(p2); mIsAngled = (p1.mX != p2.mX); } // --------------------------------------------------- // draw - Render this square and its neighboring // triangles (and other Squares, if present) // --------------------------------------------------- public void draw(Graphics2D g) { if(!mDrawn) { mDrawn = true; drawFigure(mP1, mP2, mP3, mP4, Color.red, Color.black, g); double offset = 0.0; if(mIsAngled) offset = -30; drawTriangle(mP1, mP2, mSize, 150.0 + offset, g); drawTriangle(mP2, mP3, mSize, 60.0 + offset, g); drawTriangle(mP3, mP4, mSize, -30.0 + offset, g); drawTriangle(mP4, mP1, mSize, -120.0 + offset, g); if(mNeighbor1 != null) mNeighbor1.draw(g); if(mNeighbor2 != null) mNeighbor2.draw(g); if(mNeighbor3 != null) mNeighbor3.draw(g); if(mNeighbor4 != null) mNeighbor4.draw(g); mDrawn = false; } } // --------------------------------------------------- // makeNeighbors - Create our Square's neighbors, // 'maxLevel' determines how far along // the chain of neighbors to proceed. // --------------------------------------------------- public void makeNeighbors(int maxLevel) { makeNeighbors(maxLevel, 0); } // --------------------------------------------------- // getX - Find 'x' given 'xOffset' and 'degrees' // --------------------------------------------------- private double getX(double xOffset, double degrees) { return(xOffset + mSize * Math.cos(Math.toRadians(degrees))); } // --------------------------------------------------- // getY - find 'y' given 'yOffset' and 'degrees' // --------------------------------------------------- private double getY(double yOffset, double degrees) { return(yOffset + mSize * Math.sin(Math.toRadians(degrees))); } // --------------------------------------------------- // makeNeighbors - Create our neighbors and have those // neighbors also create their neighbors // so long as 'currentLevel' is less // than 'maxLevel'. // --------------------------------------------------- public void makeNeighbors(int maxLevel, int currentLevel) { if(currentLevel++ < maxLevel) { double x1 = 0.0; double y1 = 0.0; double x2 = 0.0; double y2 = 0.0; double x3 = 0.0; double y3 = 0.0; double x4 = 0.0; double y4 = 0.0; if(mNeighbor1 == null) { // top left corner x3 = mP1.mX; y3 = mP1.mY; if(!mIsAngled) { x4 = getX(x3, -120); y4 = getY(y3, -120); x2 = getX(x3, -210); y2 = getY(y3, -210); x1 = getX(x2, -120); y1 = getY(y2, -120); } else { x4 = x3; y4 = y3 - mSize; x2 = x3 - mSize; y2 = y3; x1 = x3 - mSize; y1 = y3 - mSize; } mNeighbor1 = new Square( new XY(x1, y1), new XY(x2, y2), new XY(x3, y3), new XY(x4, y4) ); mNeighbor1.mNeighbor3 = this; } if(mNeighbor4 == null) { // top right corner x2 = mP4.mX; y2 = mP4.mY; if(!mIsAngled) { x1 = getX(x2, -120); y1 = getY(y2, -120); double a = 0.0; x3 = getX(x2, -30); y3 = getY(y2, -30); a = Math.toRadians(-120.0); x4 = getX(x3, -120); y4 = getY(y3, -120); } else { x1 = x2; y1 = y2 - mSize; x3 = x2 + mSize; y3 = y2; x4 = x2 + mSize; y4 = y2 - mSize; } mNeighbor4 = new Square( new XY(x1, y1), new XY(x2, y2), new XY(x3, y3), new XY(x4, y4) ); mNeighbor4.mNeighbor2 = this; } if(mNeighbor2 == null) { // bottom left corner x4 = mP2.mX; y4 = mP2.mY; if(!mIsAngled) { x1 = getX(x4, 150); y1 = getY(y4, 150); x3 = getX(x4, 60); y3 = getY(y4, 60); x2 = getX(x3, 150); y2 = getY(y3, 150); } else { x1 = x4 - mSize; y1 = y4; x3 = x4; y3 = y4 + mSize; x2 = x4 - mSize; y2 = y4 + mSize; } mNeighbor2 = new Square( new XY(x1, y1), new XY(x2, y2), new XY(x3, y3), new XY(x4, y4) ); mNeighbor2.mNeighbor4 = this; } if(mNeighbor3 == null) { // lower right corner x1 = mP3.mX; y1 = mP3.mY; if(!mIsAngled) { x2 = getX(x1, 60); y2 = getY(y1, 60); x4 = getX(x1, -30); y4 = getY(y1, -30); x3 = getX(x4, 60); y3 = getY(y4, 60); } else { x1 = mP3.mX; y1 = mP3.mY; x2 = x1; y2 = y1 + mSize; x3 = x1 + mSize; y3 = y1 + mSize; x4 = x1 + mSize; y4 = y1; } mNeighbor3 = new Square( new XY(x1, y1), new XY(x2, y2), new XY(x3, y3), new XY(x4, y4) ); mNeighbor3.mNeighbor1 = this; } if(mNeighbor1 != null) mNeighbor1.makeNeighbors(maxLevel, currentLevel); if(mNeighbor2 != null) mNeighbor2.makeNeighbors(maxLevel, currentLevel); if(mNeighbor3 != null) mNeighbor3.makeNeighbors(maxLevel, currentLevel); if(mNeighbor4 != null) mNeighbor4.makeNeighbors(maxLevel, currentLevel); } } // --------------------------------------------------- // drawFigure - Draw the polygon represented by the // points in 'x' and 'y' using 'fill' // and 'edge' // --------------------------------------------------- private static void drawFigure( int[] x, int[] y, Color fill, Color edge, Graphics2D g ) { g.setColor(fill); g.fillPolygon(x, y, x.length); g.setColor(edge); g.setStroke(new BasicStroke(2)); g.drawPolygon(x, y, x.length); } // --------------------------------------------------- // drawFigure - Draw the polygon represented by the // points 'p1', 'p2' and 'p3' using // 'fill' and 'edge'. // --------------------------------------------------- private static void drawFigure( XY p1, XY p2, XY p3, Color fill, Color edge, Graphics2D g ) { drawFigure( toIntArray(p1.mX, p2.mX, p3.mX), toIntArray(p1.mY, p2.mY, p3.mY), fill, edge, g ); } // --------------------------------------------------- // drawFigure - Draw the polygon represented by the // points 'p1', 'p2', 'p3' and 'p4' // using 'fill' and 'edge'. // --------------------------------------------------- private static void drawFigure( XY p1, XY p2, XY p3, XY p4, Color fill, Color edge, Graphics2D g ) { drawFigure( toIntArray(p1.mX, p2.mX, p3.mX, p4.mX), toIntArray(p1.mY, p2.mY, p3.mY, p4.mY), fill, edge, g ); } // --------------------------------------------------- // drawTriangle - Construct a triangle from 'p1', // 'p2' using angle 'degrees' and // distance 'd'. // --------------------------------------------------- private static void drawTriangle( XY p1, XY p2, double d, double degrees, Graphics2D g ) { double a = Math.toRadians(degrees); double x = p1.mX + d * Math.cos(a); double y = p1.mY + d * Math.sin(a); drawFigure(p1, p2, new XY(x, y), Color.yellow, Color.black, g); } // --------------------------------------------------- // toIntArray - Convert a set of double values into // an integer array. // --------------------------------------------------- private static int[] toIntArray(double... values) { int[] ivalues = new int[values.length]; int i = 0; for(double value : values) ivalues[i++] = (int)Math.round(value); return(ivalues); } // --------------------------------------------------- // Member Variables // --------------------------------------------------- private XY mP1; private XY mP2; private XY mP3; private XY mP4; private Square mNeighbor1; private Square mNeighbor2; private Square mNeighbor3; private Square mNeighbor4; private double mSize; private boolean mIsAngled; private boolean mDrawn; }