/* Simulation section for YHang applet */ /* Simeon Warner - 20May96 */ import java.awt.*; public class Simulation extends Thread { final int aradius=10; final int adiam = aradius+aradius; int xLeft, yLeft; int xRight, yRight; int xKnot, yKnot; int lenLeftSqd, lenRightSqd; boolean slackLeft, slackRight, stable; float weight; ControlPanel controls; DiagramPanel diagram; Simulation(ControlPanel c, DiagramPanel d) { controls = c; diagram = d; } public void init(float weight) { slackLeft = slackRight = false; this.weight=weight; controls.setWeight(weight); } public void run() { int lSqd, rSqd; // distances to left and right anchors int xk, yk; // working copies of knot coords int xkLast=0, xkLastLast=0; // previous knot x coords int downBadness, diagLBadness, diagRBadness, acrossBadness; while (true) { //System.out.println("Simulation thread running."); try { this.sleep(50); // First check to see if the knot is stable lSqd=(xKnot-xLeft)*(xKnot-xLeft)+(yKnot-yLeft)*(yKnot-yLeft); rSqd=(xKnot-xRight)*(xKnot-xRight)+(yKnot-yRight)*(yKnot-yRight); slackLeft=(lSqdxLeft) && (xKnot=((xRight-xLeft)*(yLeft-yKnot)) && (!slackLeft) && (!slackRight) ) stable=true; } else { if ((xKnot==xLeft) && (xKnot==xRight)) { stable=( !slackLeft && (yKnot>=yLeft) ) || ( !slackRight && (yKnot>=yRight) ); } else if ((xKnot==xLeft) && (yKnot>=yLeft)) stable=!slackLeft; else if ((xKnot==xRight) && (yKnot>=yRight)) stable=!slackRight; } // If knot is unstable then move, else go to sleep. if ( stable ) { // Knot stable, sleep //System.out.println("Stable, going to sleep"); diagram.repaint(); this.suspend(); } else { // Must move knot either down, diagonally or sideways // Make local copies of xKnot and yKnot xk=xKnot; yk=yKnot; // Try to make knot fall down if ((downBadness=tryMove(xk,yk+1))==Integer.MAX_VALUE) { yk++; } else { //Check for knot `outside' anchors if (xkxRight) { if (tryMove(xk-1,yk)!=Integer.MAX_VALUE) { xk--; } else if (tryMove(xk+1,yk+1)!=Integer.MAX_VALUE) { xk--; yk++; } else { yk++; } } else { // knot in between anchors, use which rope is tight to // determine which way to go if (!slackLeft) { diagLBadness=tryMove(xk-1,yk+1,true,false); acrossBadness=tryMove(xk-1,yk,true,false); if ((downBadness0) && (dr>0)) { badness=dl*dr; } else if (dl>0) { badness=dl*100; if (onRight) badness=badness*100; } else if (dr>0) { badness=dr*100; if (onLeft) badness=badness*100; } else { badness=Integer.MAX_VALUE; } return badness; } public synchronized void setAngle(float angle) { float s, c, qa, qb, qc, qq, x1, x2, dy; // make sure left is left etc. sortAnchors(); // make rope hang within bound xLeft and xRight if (xKnotxRight) xKnot=xRight; // do some sums to work out where the knot should be if (xRight==xLeft) { yKnot=(yLeft+yRight)/2; } else if (angle>(float)179.999) { // Normal algorithm not good for 180 degrees! yKnot=yLeft+((yRight-yLeft)*(xKnot-xLeft))/(xRight-xLeft); } else { dy=yRight-yLeft; x1=xKnot-xLeft; x2=xRight-xKnot; s=(float)Math.sin(angle*Math.PI/180.0); c=(float)Math.cos(angle*Math.PI/180.0); qa=s; qb=s*dy - c*(x1+x2); qc=-(s*x1*x2+c*dy*x2); qq= qb*qb - (float)4.0*qa*qc; if (qq<0.0) { System.out.println("Program error - qq<0."); qq=(float)0.0; } yKnot=yRight+(int)((-qb+(float)Math.sqrt(qq))/(qa+qa)); } controls.setAngle(angle); diagram.repaint(); } public synchronized void setWeight(float w) { this.weight=w; diagram.repaint(); } public synchronized float getWeight() { return this.weight; } public synchronized void setLeft(int x, int y) { xLeft=x; yLeft=y; } public synchronized void setRight(int x, int y) { xRight=x; yRight=y; } public synchronized void setKnot(int x, int y) { xKnot=x; yKnot=y; controls.setAngle(getAngle()); } public synchronized float getAngle() { float al,ar,angle; al=(float)Math.atan2(yKnot-yLeft,xLeft-xKnot); ar=(float)Math.atan2(yKnot-yRight,xRight-xKnot); angle=(al-ar)*(float)(180.0/Math.PI); if (angle<0.0) angle=angle+(float)360.0; return(angle); } public void checkSlack() { sortAnchors(); // set lengths (squared) whether slack or not lenLeftSqd=(xKnot-xLeft)*(xKnot-xLeft)+(yKnot-yLeft)*(yKnot-yLeft); lenRightSqd=(xKnot-xRight)*(xKnot-xRight)+(yKnot-yRight)*(yKnot-yRight); // now think about whether ropes are slack (unstable) if ((xKnotxRight) || (((xKnot-xLeft)*(yLeft-yRight))<((xRight-xLeft)*(yLeft-yKnot))) ) { slackLeft=true; slackRight=true; stable=false; //System.out.println("Slack"); } } private synchronized void sortAnchors() { int j; boolean q; if (xLeft>xRight) { j=xLeft; xLeft=xRight; xRight=j; j=yLeft; yLeft=yRight; yRight=j; j=lenLeftSqd; lenLeftSqd=lenRightSqd; lenRightSqd=j; q=slackLeft; slackLeft=slackRight; slackRight=q; } } }