import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.Font; import java.awt.Panel; import java.applet.Applet; import java.lang.String; import knot.compute.Matrix3x3; import knot.compute.Point_3D; import knot.display.Knot_Computer; import knot.display.Knot_Displayer; import knot.display.Status_Canvas; /** * Applet which displays knots being tied and untied. * @author Mac Stevens * @version 18JUL2000 */ public class Knot extends Applet { /** object to store knot list and compute knots */ Knot_Computer knot_computer; /** object to draw knots off-screen */ Knot_Displayer knot_displayer; /** object to store global data and status */ Status_Canvas status_canvas; /** off-screen image */ Image offscreenImg; /** Graphics object of off-screen image */ Graphics offscreenG; /** labels of buttons */ public final String[] BUTTON_LABELS = {" KNOT LIST ", " << ", " < ", " [] ", " > ", " >> ", " + ", " - "}; /** default name of data file */ public final String DEFAULT_DATA_FILE_NAME = "http://www.home.earthlink.net/~stevensm/knot/knotlist.dat"; /** init() method */ public void init(){ /** counter variable */ int i; /** name of data file */ String data_file_name; /** Button object */ Button button; /** Panel to hold buttons */ Panel button_panel; // make button panel button_panel = new Panel(); button_panel.setBackground(Color.black); button_panel.setSize(getSize().width,Status_Canvas.PANEL_HEIGHT); button_panel.setLocation(0,0); // make status canvas status_canvas = new Status_Canvas(this); status_canvas.setSize(Status_Canvas.COMPLETION_BAR_LENGTH, Status_Canvas.PANEL_HEIGHT); status_canvas.setLocation(0,0); status_canvas.set_screen_width(getSize().width); status_canvas.set_screen_height(getSize().height); button_panel.add(status_canvas); // make knot_computer and knot_displayer data_file_name = getParameter("datafile"); if (data_file_name.equals("")) data_file_name = DEFAULT_DATA_FILE_NAME; knot_computer = new Knot_Computer(data_file_name,status_canvas); knot_displayer = new Knot_Displayer(this,knot_computer,status_canvas); // make buttons for (i = 0;i < BUTTON_LABELS.length;i++){ button = new Button(BUTTON_LABELS[i]); button.setBackground(status_canvas.BUTTON_COLOR); button.setForeground(status_canvas.TEXT_COLOR); button.addActionListener(status_canvas); if (i == 0) button.addActionListener(knot_computer); button_panel.add(button); }// for i loop // add button_panel and knot list (java.awt.List) to applet this.setLayout(new BorderLayout(10,10)); this.add("North",button_panel); this.add("Center",knot_computer.get_awt_list()); this.addMouseListener(status_canvas); this.addMouseMotionListener(status_canvas); status_canvas.set_screen_center_X(getSize().width / 2); status_canvas.set_screen_center_Y( (getSize().height + Status_Canvas.PANEL_HEIGHT) / 2); // set up off-screen image offscreenImg = createImage(getSize().width, getSize().height); offscreenG = offscreenImg.getGraphics(); }// init() method /** starts threads */ public void start(){ if (knot_computer.isAlive()) knot_computer.resume(); else{ try{knot_computer.start();} catch(IllegalThreadStateException e){} } if (knot_displayer.isAlive()) knot_displayer.resume(); else{ try{knot_displayer.start();} catch(IllegalThreadStateException e){} } }// start() method /** pauses threads */ public void stop(){ knot_computer.suspend(); knot_displayer.suspend(); }// stop() method /** stops threads */ public void destroy(){ knot_computer.stop(); knot_displayer.stop(); super.destroy(); }// destroy() method /** draw everything */ public void paint(Graphics g){ /** image of knot */ Image knot_image; /** unit vector */ Point_3D II = new Point_3D(0.96,-0.2688,-0.0784); /** unit vector */ Point_3D JJ = new Point_3D(0.28,0.9216,0.2688); /** unit vector */ Point_3D KK = new Point_3D(0,-0.28,0.96); /** transformed unit vector: +/-I */ Point_3D XX; /** transformed unit vector: +/-J */ Point_3D YY; /** transformed unit vector: +/-K */ Point_3D ZZ; /** position vectors of cube corners (p = positive, n = negative */ Point_3D cppp, cppn, cpnp, cpnn, cnpp, cnpn, cnnp; /** array of x-coordinates */ int[] x_coordinates = new int[4]; /** array of y-coordinates */ int[] y_coordinates = new int[4]; /** transformation matrix */ Matrix3x3 mat; /** color of one face of cube */ Color color1; /** color of one face of cube */ Color color2; /** color of one face of cube */ Color color3; // if still initializing or no computed knot is available to display, // show instructions and demonstration cube if ((status_canvas.get_initialized() == false) || (knot_computer.get_index_after(0) == -1)){ // clear off-screen image offscreenG.setColor(Color.black); offscreenG.fillRect(0,0,getSize().width,getSize().height); //write instructions offscreenG.setColor(Color.white); offscreenG.setFont(new Font("TimesRoman",Font.PLAIN,32)); offscreenG.drawString("Knot Applet",12,Status_Canvas.PANEL_HEIGHT + 48); offscreenG.setFont(new Font("TimesRoman",Font.PLAIN,16)); offscreenG.drawString("Drag mouse to rotate view.",12, Status_Canvas.PANEL_HEIGHT + 96); offscreenG.drawString("Buttons:",12,Status_Canvas.PANEL_HEIGHT + 120); offscreenG.drawString("[KNOT LIST] show knot list",12, Status_Canvas.PANEL_HEIGHT + 144); offscreenG.drawString("[<<] reverse motion",12, Status_Canvas.PANEL_HEIGHT + 168); offscreenG.drawString("[ < ] slow reverse motion",12, Status_Canvas.PANEL_HEIGHT+192); offscreenG.drawString("[ [] ] stop",12,Status_Canvas.PANEL_HEIGHT+216); offscreenG.drawString("[ > ] slow forward motion",12, Status_Canvas.PANEL_HEIGHT+240); offscreenG.drawString("[>>] forward motion",12, Status_Canvas.PANEL_HEIGHT + 264); offscreenG.drawString("[ + ] zoom in",12, Status_Canvas.PANEL_HEIGHT + 288); offscreenG.drawString("[ - ] zoom out",12, Status_Canvas.PANEL_HEIGHT + 312); offscreenG.drawString("copyright (c) 2000 by Mac Stevens",12, getSize().height - 8); // compute axes and reverse if not pointing toward screen mat = status_canvas.get_transformation_matrix().multiplied_by(0.02); XX = mat.multiplied_by(II); if (XX.z < 0){ XX = XX.negative(); color1 = Color.red; } else color1 = Color.white; YY = mat.multiplied_by(JJ); if (YY.z < 0){ YY = YY.negative(); color2 = Color.yellow; } else color2 = Color.green; ZZ = mat.multiplied_by(KK); if (ZZ.z < 0){ ZZ = ZZ.negative(); color3 = Color.blue; } else color3 = Color.cyan; // compute cube corners cppp = XX.plus(YY).plus(ZZ); cppn = XX.plus(YY).minus(ZZ); cpnp = XX.minus(YY).plus(ZZ); cpnn = XX.minus(YY).minus(ZZ); cnpp = (XX.negative()).plus(YY).plus(ZZ); cnpn = (XX.negative()).plus(YY).minus(ZZ); cnnp = (XX.negative()).minus(YY).plus(ZZ); // draw cube x_coordinates[0] = status_canvas.get_screen_center_X() + ((int) cppp.x); x_coordinates[1] = status_canvas.get_screen_center_X() + ((int) cppn.x); x_coordinates[2] = status_canvas.get_screen_center_X() + ((int) cpnn.x); x_coordinates[3] = status_canvas.get_screen_center_X() + ((int) cpnp.x); y_coordinates[0] = status_canvas.get_screen_center_Y() - ((int) cppp.y); y_coordinates[1] = status_canvas.get_screen_center_Y() - ((int) cppn.y); y_coordinates[2] = status_canvas.get_screen_center_Y() - ((int) cpnn.y); y_coordinates[3] = status_canvas.get_screen_center_Y() - ((int) cpnp.y); offscreenG.setColor(color1); offscreenG.fillPolygon(x_coordinates,y_coordinates,4); x_coordinates[0] = status_canvas.get_screen_center_X() + ((int) cppp.x); x_coordinates[1] = status_canvas.get_screen_center_X() + ((int) cnpp.x); x_coordinates[2] = status_canvas.get_screen_center_X() + ((int) cnpn.x); x_coordinates[3] = status_canvas.get_screen_center_X() + ((int) cppn.x); y_coordinates[0] = status_canvas.get_screen_center_Y() - ((int) cppp.y); y_coordinates[1] = status_canvas.get_screen_center_Y() - ((int) cnpp.y); y_coordinates[2] = status_canvas.get_screen_center_Y() - ((int) cnpn.y); y_coordinates[3] = status_canvas.get_screen_center_Y() - ((int) cppn.y); offscreenG.setColor(color2); offscreenG.fillPolygon(x_coordinates,y_coordinates,4); x_coordinates[0] = status_canvas.get_screen_center_X() + ((int) cppp.x); x_coordinates[1] = status_canvas.get_screen_center_X() + ((int) cpnp.x); x_coordinates[2] = status_canvas.get_screen_center_X() + ((int) cnnp.x); x_coordinates[3] = status_canvas.get_screen_center_X() + ((int) cnpp.x); y_coordinates[0] = status_canvas.get_screen_center_Y() - ((int) cppp.y); y_coordinates[1] = status_canvas.get_screen_center_Y() - ((int) cpnp.y); y_coordinates[2] = status_canvas.get_screen_center_Y() - ((int) cnnp.y); y_coordinates[3] = status_canvas.get_screen_center_Y() - ((int) cnpp.y);; offscreenG.setColor(color3); offscreenG.fillPolygon(x_coordinates,y_coordinates,4); // put off-screen image on visible screen g.drawImage(offscreenImg,0,0,this); }// if statement (if first knot not ready) status_canvas.paint(status_canvas.getGraphics()); }// paint(Graphics g) method }// class Knot