import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; import javax.swing.*; public class NiceCurves extends JFrame implements WindowListener { JPanel curveDisp; public static int WIDTH = 700; public static int HEIGHT = 720; public NiceCurves() { setSize(WIDTH,HEIGHT); getContentPane().add(new CurveDisp()); addWindowListener(this); setVisible(true); } public void windowClosing(WindowEvent e) { System.exit(0); } public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} public static void main(String[] argv) { new NiceCurves(); } } class CurveDisp extends JPanel { private Vector ctlPoints = new Vector(); private Vector fibFig = new Vector(); PolyPoint[][] surface = new PolyPoint[4][3]; Vector[] surfM = new Vector[3]; private Graphics2D g; // Graphics private int offset = 0; public CurveDisp() { // Fill up polygon vector here ctlPoints.add(new PolyPoint(10, 10)); ctlPoints.add(new PolyPoint(200, 10)); ctlPoints.add(new PolyPoint(170, 200)); ctlPoints.add(new PolyPoint(20, 200)); surfM[0] = translate(ctlPoints, 0, 200); surfM[1] = translate(ctlPoints, 300, 500); surfM[2] = translate(ctlPoints, 30, 500); // Turn these three control polygons into a matrix for(int i=0; i < 4; i++) { surface[i][0] = (PolyPoint)(surfM[0].elementAt(i)); surface[i][1] = (PolyPoint)(surfM[1].elementAt(i)); surface[i][2] = (PolyPoint)(surfM[2].elementAt(i)); System.out.println("Added " + surface[i][0] + " at " + i + ", 0"); System.out.println("Added " + surface[i][1] + " at " + i + ", 1"); System.out.println("Added " + surface[i][2] + " at " + i + ", 2"); } fibFig.add(new PolyPoint(0,0)); fibFig.add(new PolyPoint(0, 300)); fibFig.add(new PolyPoint(300, 300)); fibFig.add(new PolyPoint(300, 0)); fibFig.add(new PolyPoint(60, 0)); fibFig.add(new PolyPoint(60, 240)); fibFig.add(new PolyPoint(240, 240)); fibFig.add(new PolyPoint(240, 60)); fibFig.add(new PolyPoint(120, 60)); fibFig.add(new PolyPoint(120, 180)); fibFig.add(new PolyPoint(150, 180)); fibFig.add(new PolyPoint(150, 90)); fibFig.add(new PolyPoint(180, 90)); fibFig.add(new PolyPoint(180, 210)); fibFig.add(new PolyPoint(90, 210)); fibFig.add(new PolyPoint(90, 30)); fibFig.add(new PolyPoint(270, 30)); fibFig.add(new PolyPoint(270, 270)); fibFig.add(new PolyPoint(30, 270)); fibFig.add(new PolyPoint(30, 0)); setSize(300, 300); } public CurveDisp(Vector newPoly) { ctlPoints = newPoly; } public void paintComponent(Graphics g) { super.paintComponent(g); this.g = (Graphics2D)g; show(fibFig, Color.red); show(splitTweak(splitTweak(splitTweak((fibFig)))), Color.yellow); show(translate(fibFig, 330, 40), Color.red); show(fourPoints(fourPoints(fourPoints(translate(fibFig, 330, 40)))), Color.yellow); /* for(int i=0; i<3; i++) { show(surfM[i], Color.red); } */ /* show(translate(ctlPoints, 330, 380), Color.black); show(splitTweak(splitTweak(splitTweak(translate(ctlPoints, 330, 380)))), Color.yellow); show(translate(ctlPoints, 60, 330), Color.black); show(fourPoints(fourPoints(fourPoints(translate(ctlPoints, 60, 330)))), Color.yellow); */ drawSurface(surface); } public Vector interleave(Vector lead, Vector second) { Vector toReturn = new Vector(); for(int i=0; i midpoint of neighbors PolyPoint secM = midPoint(left, right); // add a point on the line from M' through M to 1/8 outward // --> subtract M from M', and we have a displacement disp = new PolyPoint(currMidPoint.getX()-secM.getX(), currMidPoint.getY()-secM.getY()); // --> add 1/4th of that displacement to current midpoint newMid.add(new PolyPoint(currMidPoint.getX()+0.25*disp.getX(), currMidPoint.getY()+0.25*disp.getY())); } // after subdividing, interleave new midpoints and vertices return interleave(poly, newMid); } public Vector splitTweak(Vector poly) { // Find the midpoints Vector mid = findMidPoints(poly); Vector targets = findMidPoints(mid); Vector tweaks = new Vector(); // calculate tweaks: move poly points toward targets // start with last target for first point PolyPoint currTarget = (PolyPoint)(targets.elementAt(targets.size()-1)); PolyPoint currMidPoint = (PolyPoint)(poly.firstElement()); tweaks.add(new PolyPoint((currTarget.getX()*.5 + currMidPoint.getX()*.5), (currTarget.getY()*.5 + currMidPoint.getY()*.5))); for(int i=1; i < poly.size(); i++) { currTarget = (PolyPoint)(targets.elementAt(i-1)); currMidPoint = (PolyPoint)(poly.elementAt(i)); tweaks.add(new PolyPoint(((currTarget.getX() + currMidPoint.getX()) / 2), ((currTarget.getY() + currMidPoint.getY()))/2)); } // interleave midpoints and new tweaks return interleave(tweaks, mid); } public PolyPoint midPoint(PolyPoint first, PolyPoint second) { PolyPoint toReturn = new PolyPoint((first.getX() + second.getX())/2, (first.getY() + second.getY())/2); return toReturn; } public Vector findMidPoints(Vector orig) { Vector toReturn = new Vector(); int numPts = orig.size(); PolyPoint firstPoint = (PolyPoint)(orig.firstElement()); PolyPoint prevPoint = firstPoint, currPoint = null; // Go through point pairs and add midpoints to a return Vector for(int i=1; i < numPts; i++) { currPoint = (PolyPoint)(orig.elementAt(i)); // Find midPoint between prev and next point toReturn.add(midPoint(prevPoint, currPoint)); prevPoint = currPoint; } toReturn.add(midPoint(prevPoint, firstPoint)); return toReturn; } public void show(Vector toShow, Color drawColor) { int numPts = toShow.size(); PolyPoint currPoint, prevPoint; float currX, currY; g.setColor(drawColor); GeneralPath polygon = new GeneralPath(); currPoint = (PolyPoint)(toShow.firstElement()); currX = (float)(currPoint.getX()); currY = (float)(currPoint.getY()); polygon.moveTo(currX, currY); for(int i=1; i < numPts; i++) { currPoint = (PolyPoint)(toShow.elementAt(i)); currX = (float)(currPoint.getX()); currY = (float)(currPoint.getY()); polygon.lineTo(currX, currY); prevPoint = currPoint; } polygon.closePath(); g.draw(polygon); } public Vector translate(Vector points, float x, float y) { Vector toReturn = new Vector(); PolyPoint currPoint; for(int i=0; i < points.size(); i++) { currPoint = (PolyPoint)(points.elementAt(i)); toReturn.add(new PolyPoint(currPoint.getX()+x, currPoint.getY()+y)); } return toReturn; } public void drawPoint(PolyPoint toDraw) { offset += 1; g.drawString(offset + ": " + "(" + toDraw.getX() +", "+ toDraw.getY() + ")", (int)(toDraw.getX()), (int)(toDraw.getY())); } }