import java.awt.*; import java.awt.event.*; import java.util.*; import Geometry.*; class ControlPoint { int number; int x; int y; } public class Splines extends GenericApplet { public void render(Graphics g) { //Clear out the screen g.setColor(Color.white); g.fillRect(0, 0, bounds().width, bounds().height); //Write the mode to the top of the screen String modeString = "Mode: "; if( smooth ) modeString += "Smooth, "; else modeString += "Non-Smooth, "; if( point ) modeString += "Show Points, "; else modeString += "Hide Points, "; if( lines ) modeString += "Show Lines, "; else modeString += "Hide Lines, "; if( curve ) modeString += "Show Curve"; else modeString += "Hide Curve"; g.setColor(Color.blue); g.drawString(modeString, 0, 20); //Do nothing if no points if( points.size() == 0 ) return; //Draw the pink lines between the points if( lines ) { for(int i=1; i 1 ) { ControlPoint lastPt, newPt = new ControlPoint(); lastPt = (ControlPoint)points.elementAt(points.size()-2); newPt.x = pt.x - (lastPt.x - pt.x); newPt.y = pt.y - (lastPt.y - pt.y); points.addElement(newPt); } } //If we have a hit, record this so we can later move it else { selectedPoint = hitPoint; } //System.out.println("pt % 3 = " + selectedPoint%3); setDamage(); return true; } int threshold(int in, int min, int max) { if( in < min ) return min; else if( in > max ) return max; else return in; } public boolean mouseDrag(Event e, int x, int y) { if( selectedPoint != -1 ) { ControlPoint pt = (ControlPoint)points.elementAt(selectedPoint); //For the segment endpoints, also translate prev and next point if( smooth && (selectedPoint) % 3 == 0 ) { int dx = x - pt.x; int dy = y - pt.y; ControlPoint lastPt = ( selectedPoint - 1 >= 0 ? (ControlPoint)points.elementAt(selectedPoint-1): null ); ControlPoint nextPt = ( selectedPoint + 1 < points.size() ? (ControlPoint)points.elementAt(selectedPoint+1): null ); pt.x = threshold(x, 0, bounds().width - 1 ); pt.y = threshold(y, 0, bounds().height - 1 ); if( lastPt != null ) { lastPt.x = lastPt.x + dx; lastPt.y = lastPt.y + dy; } if( nextPt != null ) { nextPt.x = nextPt.x + dx; nextPt.y = nextPt.y + dy; } } //If the next one is an endpoint, keep the slopes the same else if( smooth && (selectedPoint % 3) == 2 && selectedPoint + 2 < points.size() ) { //if( selectedPoint + 2 < points.size() ) //{ ControlPoint pt1 = (ControlPoint)points.elementAt(selectedPoint+1); ControlPoint pt2 = (ControlPoint)points.elementAt(selectedPoint+2); pt.x = threshold(x, 0, bounds().width - 1 ); pt.y = threshold(y, 0, bounds().height - 1 ); int dx = x - pt1.x; int dy = y - pt1.y; pt2.x = pt1.x - dx; pt2.y = pt1.y - dy; //} } //If the prev one is an endpoint, keep the slopes the same else if( smooth && (selectedPoint % 3) == 1 && selectedPoint - 2 >= 0 ) { //if( selectedPoint - 2 >= 0 ) //{ ControlPoint pt1 = (ControlPoint)points.elementAt(selectedPoint-1); ControlPoint pt2 = (ControlPoint)points.elementAt(selectedPoint-2); pt.x = threshold(x, 0, bounds().width - 1 ); pt.y = threshold(y, 0, bounds().height - 1 ); int dx = x - pt1.x; int dy = y - pt1.y; pt2.x = pt1.x - dx; pt2.y = pt1.y - dy; //} } //If we have not selected smooth mode, just put the point where indicated else { pt.x = threshold(x, 0, bounds().width - 1 ); pt.y = threshold(y, 0, bounds().height - 1 ); } } setDamage(); return true; } public boolean mouseUp(Event e, int x, int y) { selectedPoint = -1; setDamage(); return true; } //Toggle a couple of settings, based on input public boolean keyDown(Event evt, int key) { switch(key) { case 's': smooth = !smooth; break; case 'l': lines = !lines; break; case 'p': point = !point; break; case 'c': curve = !curve; break; case Event.ESCAPE: points.removeAllElements(); break; } setDamage(); return true; } Vector points = new Vector(); int selectedPoint = -1; boolean smooth = true; boolean lines = true; boolean point = true; boolean curve = true; public static void main(String[] args) { Frame frame = new Frame("Splines"); Splines pnl = new Splines(); pnl.setSize(900, 900); frame.setSize(900, 900); frame.add(pnl); frame.show(); frame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { e.getWindow().dispose(); System.exit(0); } } ); pnl.init(); pnl.start(); } private void setDamage() { damage = true; } } //end class class GenericApplet extends java.applet.Applet implements Runnable { public boolean damage = true; // you can force a render public void render(Graphics g) { } // you can define how to render private Image image = null; private Graphics buffer = null; private Thread t; private Rectangle r = new Rectangle(0, 0, 0, 0); public void start() { if (t == null) { //System.out.println("Got here start"); t = new Thread(this); t.start(); } } public void stop() { //System.out.println("Got here stop"); if (t != null) { t.stop(); t = null; } } public void run() { //System.out.println("Got here run"); try { while (true) { repaint(); t.sleep(30); } } catch(InterruptedException e){}; } public void update(Graphics g) { //System.out.println("Got here update"); if (r.width != bounds().width || r.height != bounds().height) { image = createImage(bounds().width, bounds().height); buffer = image.getGraphics(); r = bounds(); damage = true; } render(buffer); damage = false; if (image != null) g.drawImage(image,0,0,this); } }