/**@(#)SquareKnot.java	29/08/2001@author Christian Mercat *  * uses Tim Lambert Splines http://www.cse.unsw.edu.au/~lambert/splines/ */import java.awt.*;import java.applet.*;import java.util.Vector;import java.lang.Math.*;/** * import java.awt.Toolkit; *         Toolkit.getDefaultToolkit().beep(); */public class SquareKnot extends Applet {	// Typical values are set but they are overwritten by the init() parameters.    public int hnum = 15;    public int vnum = 15;	public double lambda = (double) 0.25; 	// half the thickness	public double mu = (double) 0.05; 		// the shift when it bends	public double swish = (double) 0.05;	// the swishiness when it turns	public double alpha = (double) 1.3;		// controlling the smaller curve		// The main data is an array of crossings	Crossing crossings[][] = new Crossing[vnum][hnum];	Vector colors = new Vector();	// Each color corresponds to a thread.	    public void init() {		Edge edge;				// The parameters		hnum = (int) Integer.parseInt(getParameter("hnum"));		vnum = (int) Integer.parseInt(getParameter("vnum"));		lambda = (double) Integer.parseInt(getParameter("thickness"))/200;		mu = (double) Integer.parseInt(getParameter("bendshift"))/100;		swish = (double) Integer.parseInt(getParameter("swishiness"))/100;		alpha = (double) Integer.parseInt(getParameter("innercurve"))/100;		    setLayout(new GridLayout(vnum,hnum));	for (int i=0; i <vnum; i++) {	for (int j=0; j <hnum; j++) {			// We instantiate each entry.	    crossings[i][j] = new Crossing(this);		add(crossings[i][j]);		crossings[i][j].setType( 2 * ((i+j)%2));	}	}	// The vertical edges 	for (int i=0; i <vnum; i++) {	for (int j=1; j <hnum; j++) {			edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[i][j-1], crossings[i][j]);		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[i][j-1].setEdges(edge, 2);		crossings[i][j].setEdges(edge, 0);		edge.setLabels( 2, 0);// Conversely, the edge of each crossing in a given direction is that edge./* 0 = W, * 1 = N, * 2 = E, * 3 = S.  */	}	} 	for (int i=0; i <vnum; i++) {			edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[i][0], crossings[i][0]); //Only one.		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[i][0].setEdges(edge, 0);		edge.setLabels( 0, 0);		edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[i][hnum-1], crossings[i][hnum-1]);		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[i][hnum-1].setEdges(edge, 2);		edge.setLabels( 2, 2);// Conversely, the edge of each crossing in a given direction is that edge./* 0 = W, * 1 = N, * 2 = E, * 3 = S.  */	}	// the horizontal edges 	for (int j=0; j <hnum; j++) {	for (int i=1; i <vnum; i++) {			edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[i-1][j], crossings[i][j]);		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[i-1][j].setEdges(edge, 1);		crossings[i][j].setEdges(edge, 3);		edge.setLabels( 1, 3);// Conversely, the edge of each crossing in a given direction is that edge.	}	} 	for (int j=0; j <hnum; j++) {		edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[0][j], crossings[0][j]);		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[0][j].setEdges(edge, 3);		edge.setLabels( 3, 3);		edge = new Edge();		edge.setColor(getBackground()); // For it not to show.		edge.setCrossings(crossings[vnum-1][j], crossings[vnum-1][j]);		 // The edge is associated with 2 neighbouring crossings (faces).		crossings[vnum-1][j].setEdges(edge, 1);		edge.setLabels( 1, 1);// Conversely, the edge of each crossing in a given direction is that edge.	}   }    public boolean handleEvent(Event e) {	switch (e.id) {	  case Event.WINDOW_DESTROY:	    System.exit(0);	    return true;	  default:	    return false;	}    } ////////////////////////////    public static void main(String args[]) {	Frame f = new Frame("SquareKnot");	SquareKnot squareKnot = new SquareKnot();	squareKnot.init();	squareKnot.start();	f.add("Center", squareKnot);	/**	 * f.resize(squareKnot.hnum * squareKnot.size, 	 *          squareKnot.vnum * squareKnot.size);	 */	f.show();    }} //////////////////////////// ////////////////////////////class Crossing extends Canvas {	public SquareKnot squareKnot;	// Its container.    public Edge[] edges = new Edge[4]; 	/*  The edges themselves are instantiated by the main init() method	 *  because they relate two Crossings objects.	 */	public int type;/* 0 = SW-NE wall, * 1 = Horizontal over, * 2 = NW-SE wall, * 3 = Vertical over.  */	public Vector bezs;/**	The Bezier curves */	public Vector colors;// Their colors	 ////////////////////////////	    public Crossing(SquareKnot squareKnot) {		this.squareKnot = squareKnot;		bezs = new Vector();  // It will be set when the type is fixed.	setBackground(Color.white);    } ////////////////////////////   public void setEdges(Edge edge, int label) {if ((0<= label) && (label <= 3)) {	// Note: on the boundary of the canvas, the edges are null.   		this.edges[label] = edge;   				} else {	throw new IllegalArgumentException();}   }    ////////////////////////////    public void setType(int type) {if ((0<= type) && (type <= 3)) {			this.type = type;		for(int i=0;i<4;i++) {			if(edges[i]!=null) {				edges[i].otherCrossing(this).setBeziers();				edges[i].setColor(new Color((float)Math.random(),(float)Math.random(),(float)Math.random()));				}		}					setColors();	setBeziers();	repaint();			} else {	throw new IllegalArgumentException();}	} ////////////////////////////  	 public void setBeziers() {	  Vector bezs = new Vector(); // The Bezier curves	  Bezier bez;                 // The iteration variable	  int h =  size().height;	  int w = size().width;	  double lambda = squareKnot.lambda;	  double alpha = squareKnot.alpha*(.5 -1.8*lambda)/(.5 -lambda);	  double a; // The alpha factor for the plain ones.	  	  	  	    switch (type) {	case 0: // SW-NE Wall	  if((edges[1]!=null)&&(edges[2]!=null)) {	bez = new Bezier();	bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w,  h);	bez.addPoint((.5-(lambda-mu(1)-nu(1))*rho(1)) * w,  (.5+lambda) * h);/** *       if ( *  (edges[1].otherCrossing(this).type == 2)&& // The other type of wall *  (edges[2].otherCrossing(this).type == 2) // Again * ) { // Then it's an earlike end. *     bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w,  h); *     bez.addPoint((.5) * w,  (.5) * h); *     bez.addPoint(              w,  (.5-(lambda-mu(2))*rho(2)) * h); *       } */	bez.addPoint((.5+lambda) * w,  (.5-(lambda-mu(2)-nu(2))*rho(2)) * h);	bez.addPoint(              w,  (.5-(lambda-mu(2))*rho(2)) * h);bezs.addElement(bez);	bez = new Bezier();	bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w,  h);	bez.addPoint((.5+(lambda+mu(1)+alpha*nu(1))*rho(1)) * w,  (.5+1.8*lambda) * h);/** *       if ( *  (edges[1].otherCrossing(this).type == 2)&& // The other type of wall *  (edges[2].otherCrossing(this).type== 2) // Again * ) { // Then it's an earlike end. *     bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w,  h); *     bez.addPoint((.5+1.4*lambda) * w,  (.5+1.4*lambda) * h); *     bez.addPoint(              w,  (.5+(lambda+mu(2))*rho(2)) * h); *       } */	bez.addPoint((.5+1.8*lambda) * w,  (.5+(lambda+mu(2)+alpha*nu(2))*rho(2)) * h);	bez.addPoint(              w,  (.5+(lambda+mu(2))*rho(2)) * h);bezs.addElement(bez);	  }	  if((edges[0]!=null)&&(edges[3]!=null)) {	bez = new Bezier();  	bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w,  0);  	bez.addPoint((.5+(lambda+mu(3)+nu(3))*rho(3)) * w,  (.5-lambda) * h);/** *       if ( *  (edges[0].otherCrossing(this).type == 2)&& // Another wall *  (edges[3].otherCrossing(this).type == 2) // The same * ) { // Then it's an earlike end. *     bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w,  0); *     bez.addPoint((.5) * w,  (.5) * h); *     bez.addPoint(           0,  (.5+(lambda+mu(0))*rho(0)) * h); *       } */	bez.addPoint((.5-lambda) * w,  (.5+(lambda+mu(0)+nu(0))*rho(0)) * h); 	bez.addPoint(           0,  (.5+(lambda+mu(0))*rho(0)) * h);bezs.addElement(bez);  	bez = new Bezier();	bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w, 0);	bez.addPoint((.5-(lambda-mu(3)-alpha*nu(3))*rho(3)) * w,  (.5-1.8*lambda) * h);/** *       if ( *  (edges[0].otherCrossing(this).type == 2)&& // Another wall *  (edges[3].otherCrossing(this).type== 2) // The same * ) { // Then it's an earlike end. *     bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w, 0); *     bez.addPoint((.5-1.4*lambda) * w,  (.5-1.4*lambda) * h); *     bez.addPoint(              0,  (.5-(lambda-mu(0))*rho(0)) * h); *       } */	bez.addPoint((.5-1.8*lambda) * w,  (.5-(lambda-mu(0)-alpha*nu(0))*rho(0)) * h);	bez.addPoint(              0,  (.5-(lambda-mu(0))*rho(0)) * h);bezs.addElement(bez);	  }	  		break;	case 1: // Vertical above	  if((edges[1]!=null)&&(edges[3]!=null)) {	  bez = new Bezier();	  bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w, 				 h);	  if (edges[1].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-(lambda-mu(1)-a*nu(1))*rho(1)) * w, (.5+lambda) * h);	  if (edges[3].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-(lambda-mu(3)-a*nu(3))*rho(3)) * w, (.5-lambda) * h);	  bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w, 				 0);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w, 				 h);	  if (edges[1].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+(lambda+mu(1)+a*nu(1))*rho(1)) * w, (.5+lambda) * h);	  if (edges[3].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+(lambda+mu(3)+a*nu(3))*rho(3)) * w, (.5-lambda) * h);	  bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w, 				 0);bezs.addElement(bez);	  if(edges[0]!=null) {	  bez = new Bezier();	  bez.addPoint( 				    0,  (.5-(lambda-mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.25-(lambda-mu(1)-mu(3))/2) * w,  (.5-(lambda-mu(0)-.5*a*nu(0))*rho(0)) * h);	  bez.addPoint((.25-(lambda-mu(1)-mu(3))/2) * w,  (.5-lambda) * h);	  bez.addPoint((.5-lambda) *    w,  (.5-lambda) * h);bezs.addElement(bez);	bez = new Bezier();	bez.addPoint(				  0,  (.5+(lambda+mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	bez.addPoint((.25-(lambda-mu(1)-mu(3))/2) * w,  (.5+(lambda+mu(0)+.5*a*nu(0))*rho(0)) * h);	bez.addPoint((.25-(lambda-mu(1)-mu(3))/2) * w,  (.5+lambda) * h);	bez.addPoint((.5-lambda) *    w,  (.5+lambda) * h);bezs.addElement(bez);}	 	  	  if(edges[2]!=null) {	  bez = new Bezier();	  bez.addPoint(				    w,  (.5-(lambda-mu(2))*rho(2)) * h);	  if (edges[2].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.75+(lambda+mu(1)+mu(3))/2) * w,  (.5-(lambda-mu(2)-.5*a*nu(2))*rho(2)) * h);	  bez.addPoint((.75+(lambda+mu(1)+mu(3))/2) * w,  (.5-lambda) * h);	  bez.addPoint((.5+lambda) *    w,  (.5-lambda) * h);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint(				    w,  (.5+(lambda+mu(2))*rho(2)) * h);	  if (edges[2].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.75+(lambda+mu(1)+mu(3))/2) * w,  (.5+(lambda+mu(2)+.5*a*nu(2))*rho(2)) * h);	  bez.addPoint((.75+(lambda+mu(1)+mu(3))/2) * w,  (.5+lambda) * h);	  bez.addPoint((.5+lambda) *    w,  (.5+lambda) * h);bezs.addElement(bez);}} else {	if((edges[0]!=null)&&(edges[2]!=null)) {	  bez = new Bezier();	  bez.addPoint( 			 0,   (.5+(lambda+mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-lambda) * w,  (.5+(lambda+mu(0)+a*nu(0))*rho(0)) * h);	  if (edges[2].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+lambda) * w,  (.5+(lambda+mu(2)+a*nu(2))*rho(2)) * h);	  bez.addPoint(				 w,  (.5+(lambda+mu(2))*rho(2)) * h);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint( 			 0,   (.5-(lambda-mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-lambda) * w,  (.5-(lambda-mu(0)-a*nu(0))*rho(0)) * h);	  if (edges[2].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+lambda) * w,  (.5-lambda+mu(2)+a*nu(2)) * h);	  bez.addPoint(				 w,  (.5-lambda+mu(2)) * h);bezs.addElement(bez);	  }	  }	  		break;	case 2: // SE-NW wall	  if((edges[0]!=null)&&(edges[1]!=null)) {	  bez = new Bezier();	  bez.addPoint(				 0,  (.5+(lambda+mu(0))*rho(0)) * h);	  bez.addPoint((.5-1.8*lambda) * w,  (.5+(lambda+mu(0)+alpha*nu(0))*rho(0)) * h);/** *       if ( *  (edges[0].otherCrossing(this).type == 0)&& // A different wall *  (edges[1].otherCrossing(this).type == 0) // The same wall * ) { // Then it's an earlike end. *       bez.addPoint(              0,  (.5+(lambda+mu(0))*rho(0)) * h); *       bez.addPoint((.5-1.4*lambda) * w,  (.5+1.4*lambda) * h); *       bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w,                h); *       } */	  bez.addPoint((.5-(lambda-mu(1)-alpha*nu(1))*rho(1)) * w,  (.5+1.8*lambda) * h);	  bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w,  			  h);  bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint(				 0,  (.5-(lambda-mu(0))*rho(0)) * h);	  bez.addPoint((.5-lambda) * w,  (.5-(lambda-mu(0)-nu(0))*rho(0)) * h);/** *       if ( *  (edges[0].otherCrossing(this).type == 0)&& // A different wall *  (edges[1].otherCrossing(this).type == 0) // The same wall * ) { // Then it's an earlike end. *       bez.addPoint(              0,  (.5-(lambda-mu(0))*rho(0)) * h); *       bez.addPoint((.5) * w,  (.5) * h); *       bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w,                h); *       } */	  bez.addPoint((.5+(lambda+mu(1)+nu(1))*rho(1)) * w,  (.5+lambda) * h);	  bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w,  			  h);  bezs.addElement(bez);	  }	  if((edges[2]!=null)&&(edges[3]!=null)) {	  bez = new Bezier();	  bez.addPoint(				 w,  (.5+(lambda+mu(2))*rho(2)) * h);	  bez.addPoint((.5+lambda) * w,  (.5+(lambda+mu(2)+nu(2))*rho(2)) * h);/** *       if ( *  (edges[2].otherCrossing(this).type == 0)&& // A different wall *  (edges[3].otherCrossing(this).type == 0) // The same wall * ) { // Then it's an earlike end. *       bez.addPoint(              w,  (.5+(lambda+mu(2))*rho(2)) * h); *       bez.addPoint((.5) * w,  (.5) * h); *       bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w,                0); *       } */	  bez.addPoint((.5-(lambda-mu(3)-nu(3))*rho(3)) * w,  (.5-lambda) * h);	  bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w,  			  0);  bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint(				 w,  (.5-(lambda-mu(2))*rho(2)) * h);	  bez.addPoint((.5+1.8*lambda) * w,  (.5-(lambda-mu(2)-alpha*nu(2))*rho(2)) * h);/** *       if ( *  (edges[2].otherCrossing(this).type == 0)&& // A different wall *  (edges[3].otherCrossing(this).type == 0) // The same wall * ) { // Then it's an earlike end. *       bez.addPoint(              w,  (.5-(lambda-mu(2))*rho(2)) * h); *       bez.addPoint((.5+1.8*lambda) * w,  (.5-1.8*lambda) * h); *       bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w,                0); *       } */	  bez.addPoint((.5+(lambda+mu(3)+alpha*nu(3))*rho(3)) * w,  (.5-1.8*lambda) * h);	  bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w,   			  0);  bezs.addElement(bez);	  }		break;	case 3: // Horizontal above	  if((edges[0]!=null)&&(edges[2]!=null)) {	  bez = new Bezier();	  bez.addPoint( 			 0,   (.5+(lambda+mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-lambda) * w,  (.5+(lambda+mu(0)+a*nu(0))*rho(0)) * h);	  if (edges[2].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+lambda) * w,  (.5+(lambda+mu(2)+a*nu(2))*rho(2)) * h);	  bez.addPoint(				 w,  (.5+(lambda+mu(2))*rho(2)) * h);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint( 			 0,   (.5-(lambda-mu(0))*rho(0)) * h);	  if (edges[0].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-lambda) * w,  (.5-(lambda-mu(0)-a*nu(0))*rho(0)) * h);	  if (edges[2].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+lambda) * w,  (.5-lambda+mu(2)+a*nu(2)) * h);	  bez.addPoint(				 w,  (.5-lambda+mu(2)) * h);bezs.addElement(bez);	  if(edges[1]!=null) {	  bez = new Bezier();	  bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w, 				  h);	  if (edges[1].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-(lambda-mu(1)-.5*a*nu(1))*rho(1)) * w,  (.75+(lambda+mu(0)+mu(2))/2) * h);	  bez.addPoint((.5-lambda) * w,  (.75+lambda/2) * h);	  bez.addPoint((.5-lambda) * w,  (.5+lambda) * h);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w, 				  h);	  if (edges[1].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+(lambda+mu(1)+.5*a*nu(1))*rho(1)) * w,  (.75+(lambda+mu(0)+mu(2))/2) * h);	  bez.addPoint((.5+lambda) * w,  (.75+lambda/2) * h);	  bez.addPoint((.5+lambda) * w,  (.5+lambda) * h);bezs.addElement(bez);}	  if(edges[3]!=null) {		bez = new Bezier();		bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w, 				  0);	  if (edges[3].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}		bez.addPoint((.5-(lambda-mu(3)-.5*a*nu(3))*rho(3)) * w,  (.25-(lambda-mu(0)-mu(2))/2) * h);		bez.addPoint((.5-lambda) * w,  (.25-lambda/2) * h);		bez.addPoint((.5-lambda) * w,  (.5-lambda) * h);bezs.addElement(bez);		bez = new Bezier();		bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w,  				  0);	  if (edges[3].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}		bez.addPoint((.5+(lambda+mu(3)+.5*a*nu(3))*rho(3)) * w,  (.25-(lambda-mu(0)-mu(2))/2) * h);		bez.addPoint((.5+lambda) * w,  (.25-lambda/2) * h);		bez.addPoint((.5+lambda) * w,  (.5-lambda) * h);bezs.addElement(bez);	  }} else {	  if((edges[1]!=null)&&(edges[3]!=null)) {	  bez = new Bezier();	  bez.addPoint((.5-(lambda-mu(1))*rho(1)) * w, 				 h);	  if (edges[1].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-(lambda-mu(1)-a*nu(1))*rho(1)) * w, (.5+lambda) * h);	  if (edges[3].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5-(lambda-mu(3)-a*nu(3))*rho(3)) * w, (.5-lambda) * h);	  bez.addPoint((.5-(lambda-mu(3))*rho(3)) * w, 				 0);bezs.addElement(bez);	  bez = new Bezier();	  bez.addPoint((.5+(lambda+mu(1))*rho(1)) * w, 				 h);	  if (edges[1].otherCrossing(this).type==2) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+(lambda+mu(1)+a*nu(1))*rho(1)) * w, (.5+lambda) * h);	  if (edges[3].otherCrossing(this).type==0) {a = 1/alpha;} else { a=1;}	  bez.addPoint((.5+(lambda+mu(3)+a*nu(3))*rho(3)) * w, (.5-lambda) * h);	  bez.addPoint((.5+(lambda+mu(3))*rho(3)) * w, 				 0);bezs.addElement(bez);}	  }	  		break;	default: 	  }  this.bezs = bezs;  } ////////////////////////////	  public double mu(int e) {	  double themu = squareKnot.mu;  	  int otherType;  	  	  if (edges[e]==null) {	  	return(0);	  }	  /**	   * if (1==1) {	   *   return(0);	   * }	   */	  	  	  otherType = edges[e].otherCrossing(this).type;	    switch ((type % 2) + (otherType %2)) { // The switch formula should be symmetric in the 2 types to ensure continuity.  	case 0:  // Both are walls	  if (type == otherType) {	  		  return((double) 0); // no wiggling when it's straight.	  } else { 		  /**		   * It's a corner, the sign depends on the type of crossing 		   * & the label of the edge. They are invariant under		   * type -> 2 - type && edge -> 2 - edge 		   */		switch (2*type + e) {  			case 0:			  return((double) - themu);			case 1:			  return((double) + themu);  			case 2:			  return((double) + themu);			case 3:			  return((double) - themu);			case 4:			  return((double) + themu);			case 5:			  return((double) - themu);			case 6:			  return((double) - themu);			case 7:			  return((double) + themu);			default:	  		  throw new IllegalArgumentException();		}	  }	case 1: // One wall	  if ((type % 2) == 0) { // It's a wall		switch (2*type + e) { // Then the same as before.			case 0:			  return((double) - themu);			case 1:			  return((double) + themu);  			case 2:			  return((double) + themu);			case 3:			  return((double) - themu);			case 4:			  return((double) + themu);			case 5:			  return((double) - themu);			case 6:			  return((double) - themu);			case 7:			  return((double) + themu);			default:	  		  throw new IllegalArgumentException();		}	  } else { // The other one is a wall. Return what the other one gives.		 return(edges[e].otherCrossing(this).mu(edges[e].otherLabel(e)));	  }	case 2: // Both are plain	  return((double) 0);	default: 	  throw new IllegalArgumentException();  } }  //////////////////////////// public int signum(double num) { // I don't know how it's called in usual java. 	if (num > 0) { 		return(1); 	} 	if (num < 0) { 		return(-1); 	} 		return(0); } 	     public double nu(int e) {	  double lambda = squareKnot.lambda;	  double swish = squareKnot.swish;  	  int otherType;  	  	  if (edges[e]==null) {	  	return(0);	  }	  /**	   * if (1==1) {	   *   return(mu(e));	   * }	   */	  	  	  otherType = edges[e].otherCrossing(this).type;	     switch ((type % 2) + (otherType %2)) { // The switch formula should be symmetric in the 2 types to ensure continuity.  	case 0:  // Both are walls	  if (type == otherType) {		return((double) -(type-1)*signum((e+1)%4-1.5)*(.5-lambda)/rho(e)); 			  // no wiggling when it's straight.	  } else {		   return(signum(mu(e))*(swish)*squareKnot.mu); // Same sign as mu. 	  }	 	case 1: // One wall	  return(-signum(mu(e))*(2*(type %2)-1)*swish); /**	  Same or opposite sign as mu depending if it's a wall (type%2 ==0) or if it is not (==1). */	case 2: // Both are plain	  return((double) 0);	default: 	  throw new IllegalArgumentException();  }}  ////////////////////////////     public double rho(int e) {  	  int otherType;  	  	  if (edges[e]==null) {	  	return((double) 1);	  }	  /**	   * if (1==1) {	   *   return(1);	   * }	   */	  	  otherType = edges[e].otherCrossing(this).type;	     switch ((type % 2) + (otherType %2)) { // The switch formula should be symmetric in the 2 types to ensure continuity.  	case 0:  // Both are walls	  return((double) 1.4); // Slanted. 	case 1: // One wall	  return((double) 1.1); 	case 2: // Both are plain	  return(1);	default: 	  throw new IllegalArgumentException();  }}  ////////////////////////////    public void setBezColors() {	  Vector cols = new Vector(); // The colors	  	  // First be sure that the Bezier curves are set.	  if (bezs.isEmpty() ) {setBeziers();	  }  //Then follow exactly the same switch pattern.  switch (type) {	case 0: // SW-NE Wall	  if((edges[1]!=null)&&(edges[2]!=null)) {cols.addElement((Color) edges[1].getColor());cols.addElement((Color) edges[1].getColor());	  }	  if((edges[0]!=null)&&(edges[3]!=null)) {cols.addElement((Color) edges[0].getColor());cols.addElement((Color) edges[0].getColor());	  }	  		break;	case 1: // Vertical above	  if ((edges[1]!=null)&&(edges[3]!=null)) {cols.addElement((Color) edges[1].getColor());cols.addElement((Color) edges[1].getColor());	  		if (edges[0]!=null) {cols.addElement((Color) edges[0].getColor());cols.addElement((Color) edges[0].getColor());	  		} 	  		if (edges[2]!=null) {cols.addElement((Color) edges[2].getColor());cols.addElement((Color) edges[2].getColor());	  		}	  } 	  else {	  	if ((edges[0]!=null)&&(edges[2]!=null)) {cols.addElement((Color) edges[0].getColor());cols.addElement((Color) edges[0].getColor());		}	  }		break;	case 2: // SE-NW wall	  if(edges[0]!=null) {cols.addElement((Color) edges[0].getColor());cols.addElement((Color) edges[0].getColor());	  }	  if(edges[2]!=null) {cols.addElement((Color) edges[2].getColor());cols.addElement((Color) edges[2].getColor());	  }		break;	case 3: // Horizontal above	  if ((edges[0]!=null)&&(edges[2]!=null)) {cols.addElement((Color) edges[0].getColor());cols.addElement((Color) edges[0].getColor());	  		if (edges[1]!=null) {cols.addElement((Color) edges[1].getColor());cols.addElement((Color) edges[1].getColor());	  		} 	  		if (edges[3]!=null) {cols.addElement((Color) edges[3].getColor());cols.addElement((Color) edges[3].getColor());	  		}	  } 	  else {	  	if ((edges[1]!=null)&&(edges[3]!=null)) {cols.addElement((Color) edges[1].getColor());cols.addElement((Color) edges[1].getColor());		}	  }		break;	default: 			throw new IllegalArgumentException();  }  this.colors = cols; }  ////////////////////////////   public void setColors() {		for(int i=0;i<4;i++) {			if(edges[i]!=null)	{	  // perform the recursive setting along the thread in both directions.	  setColors(i);	  edges[i].otherCrossing(this).setColors(edges[i].otherLabel(i));	  		}   		} }  ////////////////////////////  public void setColors(int e) {	  	int next; 		// The label of the next edge in the crossing following the thread starting at label e.		Edge nextE; 	// The next Edge (a shortcut).		Crossing nextC; // The next crossing	if (edges[e]!=null) 	{ 		switch (type) { // The next edge depends on the type of crossing. 	case 0: // SW-NE Wall 	  next = (3-e)%4; 	  break; 	case 1: // Vertical above	  next = (2+e)%4;	  break;   	case 2: // SE-NW wall 	  next = (5-e)%4; 	  break;	case 3: // Horizontal above 	  next = (2+e)%4; 	  break; 	default: throw new IllegalArgumentException(); } /** * System.out.println("type"); * System.out.println(type); * System.out.println(e); * System.out.println(next); * System.out.println(colors); */nextE = edges[next];    		if(nextE != null) {  			if (nextE.getColor()!=edges[e].getColor()) {			nextE.setColor(edges[e].getColor()); 			nextC = nextE.otherCrossing(this);	 		nextC.setColors(nextE.otherLabel(next));		}	}		}	setBezColors();	repaint();	}  ////////////////////////////     public boolean handleEvent(Event e) {	switch (e.id) {	  case Event.MOUSE_UP:	   setType( (this.type + 1) % 4);	    repaint();	    return true;	  case Event.MOUSE_DRAG:	    return true;	  case Event.WINDOW_DESTROY:	    System.exit(0);	    return true;	  default:	    return false;	}    } ////////////////////////////	public void paint(Graphics g) {	g.setColor(getForeground());	g.setPaintMode();//	g.drawRect(0,0, size().width, size().height);	for (int i = 0; i<bezs.size() ; i++) {				g.setColor((Color)colors.elementAt(i));				((Bezier)bezs.elementAt(i)).paint(g);		 }	/** *	g.setColor(getForeground()); * switch (type) { *     case 0:     g.drawLine(0, size().height, size().width, 0); *     break; *     case 1:     g.drawLine(size().width / 2, 0, *                         size().width / 2, size().height); *     break; *     case 2:     g.drawLine(0, 0, size().width, size().height); *     break; *     case 3:     g.drawLine(0, size().height / 2, *                         size().width, size().height / 2); * } */// g.drawString(Integer.toString(type),size().width / 2,size().height / 2);} //////////////////////////// public Dimension preferredSize() {                  return minimumSize();              } //////////////////////////// public synchronized Dimension minimumSize() {                  return new Dimension  (squareKnot.size().width / squareKnot.hnum,  squareKnot.size().height / squareKnot.vnum);              }} //////////////////////////// ////////////////////////////class Edge {	public Crossing[] crossings = new Crossing[2];	/* The two crossings which have this edge in common.	 * Instantiated by the main init().	 */	public int[] labels;	/* The label of the direction corresponding to this edge	 * for each of the 2 crossings.	 */	public Color color;	// The color corresponds to a thread.	public Edge() {	}	public void setCrossings(Crossing[] crossings) {   	this.crossings = crossings;   }	public void setCrossings(Crossing crossing1, Crossing crossing2) {   	setCrossings(new Crossing[] {crossing1, crossing2});   }   public void setLabels(int[] labels) {   	this.labels = labels;   }   public void setLabels(int label1, int label2) {   	setLabels(new int[] {label1, label2});   }   public void setColor(Color color) {   	this.color = color;   }      public Color getColor() {   	return(this.color);   }       public Crossing otherCrossing(Crossing c) {   if (c == crossings[0]) {return crossings[1];} else {return crossings[0];};   }       public int otherLabel(int l) {   if (l == labels[0]) {return labels[1];} else {return labels[0];};   }   }	    