class TrafficPanel extends Applet implements Runnable {
TrafficSystem graph;
int nnodes;
int lghtOrStp;
Node nodes[] = new Node[100];
ChangeLight light[] = new ChangeLight[5];
CalFlow carpermin[] = new CalFlow[5];
Thread relaxer, flow;
int brgflag[] = new int[5];
double speed=10;
int carwidth=6, carlength=9;
int xpos[]= new int[5];
int ypos=200;
int brgright[] = new int[5];
int brgleft[] = new int[5];
int brgtop =ypos+ carlength;
int brgbottom=ypos- carlength;
int rdleft[]=new int[5];
int rdright[] = new int[5];
int rdtop= ypos+ carwidth, rdbottom= ypos- carwidth;
TrafficPanel(TrafficSystem graph) {
lghtOrStp=1; //stop :0, light: 1
this.graph = graph;
for (int i=0; i<5; i++)
{
light[i]= new ChangeLight();
carpermin[i]= new CalFlow();
xpos[i]=150*(i+1);
brgright[i]=xpos[i]- carlength;
brgleft[i]=xpos[i]+ carlength;
brgflag[i]=0;
}
for(int k=1; k<4; k++){
rdleft[k]= xpos[k-1]- carwidth;
rdright[k]= xpos[k-1]+ carwidth;
}
rdleft[0]=0;
rdright[0]=0;
}
int findNode(String lbl) {
for (int i = 0 ; i < nnodes ; i++) {
if (nodes[i].lbl.equals(lbl)) {
return i;
}
}
return addNode(lbl);
}
int addNode(String lbl) {
int temp;
Node n = new Node();
temp = (int)(5*Math.random());
if (temp==0||temp==4){
n.x = 480 + 210*Math.random();
n.y= ypos;
n.carW=carlength;
n.carL=carwidth;
}
else{
n.x= xpos[temp-1];
n.y= 10+100*Math.random();
n.carW=carwidth;
n.carL=carlength;
}
// temp=(int)(3*Math.random()); // three lanes
// n.y = 150+50*temp;
if (temp==4)
temp=0;
n.road=temp;
n.lbl = lbl;
n.carWaiting=-1;
nodes[nnodes] = n;
return nnodes++;
}
public void run() {
for (int j=0; j<5; j++)
light[j].signal=1;
flow = new Thread(carpermin[0]);
carpermin[0].time0 = System.currentTimeMillis();
carpermin[0].carnum=0;
flow.start();
while (true) {
relax();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
break;
}
}
}
synchronized void relax() {
for (int i = 0 ; i < nnodes; i++) {
if (nodes[i].road==0){
nodes[i].dx = -speed*Math.random();
nodes[i].dy = 2*Math.random()-1;
}
else{
nodes[i].dy = speed*Math.random();
nodes[i].dx = 2*Math.random()-1;
}
}
for (int i = 0 ; i < nnodes ; i++) {
Node n1 = nodes[i];
double dx = 0;
double dy = 0;
for (int j = 0 ; j < nnodes ; j++) {
Node n2 = nodes[j];
if (i == j||n1.road!=n2.road) {
continue;
}
double vx;
if(n1.road==0)
vx = n1.x - n2.x;
else
vx= n2.y-n1.y;
if (vx<0)
continue;
double len=vx;
if( len<(n2.carW+n2.carL)){
if (n1.carWaiting<0)
n1.carWaiting= System.currentTimeMillis();
if(n1.road==0)
n1.dx=0;
else
n1.dy=0;
}
}
}
//move a car
Dimension d = size();
double temp;
for (int i = 0 ; i < nnodes ; i++) {
Node n = nodes[i];
if(n.road==0){
temp=n.x;
n.x += Math.max(-10, Math.min(10, n.dx));
for (int k=0; k<3; k++){
if ((n.x<brgleft[k]&&n.x>brgright[k])&&brgflag[k]==1){
if(temp> brgleft[k] ||temp<brgright[k])
n.x=temp;
}
else if ((n.x< brgleft[k] &&n.x>brgright[k])&&brgflag[k]==0)
if (lghtOrStp==0)
brgflag[k]=1;
else{
if (light[k].signal==0)
brgflag[k]=1;
else
n.x=temp;
}
else if(temp< brgleft[k] &&temp>brgright[k])
brgflag[k]=0;
if (n.x < 0) {
n.x = d.width-10*Math.random();
carpermin[0].carnum=carpermin[0].carnum+1;
} else if (n.x > d.width) {
n.x = d.width-10*Math.random();
}
if (n.x!=temp && n.carWaiting==-1){
carpermin[0].carwt+= System.currentTimeMillis()-n.carWaiting;
n.carWaiting=-1;
}
}
}
else{
temp=n.y;
n.y += Math.max(-10, Math.min(10, n.dy));
if ((n.y<brgtop&&n.y>brgbottom)&&brgflag[n.road-1]==1){
if(temp> brgtop ||temp<brgbottom)
n.y=temp;
}
else if ((n.y< brgtop &&n.y>brgbottom)&&brgflag[n.road-1]==0)
if (lghtOrStp==0)
brgflag[n.road-1]=1;
else{
if (light[n.road-1].signal==1)
brgflag[n.road-1]=1;
else
n.y=temp;
}
else if(temp< brgtop &&temp>brgbottom)
brgflag[n.road-1]=0;
if (n.y > d.height||n.y<0) {
n.y = 10*Math.random();
carpermin[0].carnum=carpermin[0].carnum+1;
}
}
}
repaint();
}
Node pick;
double pickoldx, pickoldy;
Image offscreen;
Dimension offscreensize;
Graphics offgraphics;
final Color selectColor = Color.pink;
final Color edgeColor = Color.black;
final Color nodeColor = new Color(250, 220, 100);
public void paintNode(Graphics g, Node n) {
int x = (int)n.x;
int y = (int)n.y;
g.setColor((n==pick) ? selectColor : nodeColor);
int w= n.carW;
int h=n.carL;
g.fillRect(x - w/2, y - h / 2, w, h);
g.setColor(Color.black);
g.drawRect(x - w/2, y - h / 2, w-1, h-1);
g.drawString(".", x-w/2+2, y+h/2-2);
}
public void paintRoad(Graphics g){
Dimension d = size();
g.setColor(Color.gray);
for(int k=1; k<4; k++){
g.drawLine(rdleft[k], 0, rdleft[k], rdbottom);
g.drawLine(rdleft[k], rdtop, rdleft[k], d.height);
g.drawLine(rdright[k], 0, rdright[k], rdbottom);
g.drawLine(rdright[k], rdtop, rdright[k], d.height);
g.drawLine(rdright[k-1], rdtop, rdleft[k], rdtop);
g.drawLine(rdright[k-1], rdbottom, rdleft[k], rdbottom);
}
g.drawLine(rdright[3], rdbottom, d.width, rdbottom);
g.drawLine(rdright[3], rdtop, d.width, rdtop);
}
public void paintLghtPeriod(Graphics g){
Font warnFont, dispFont, stopFont;
warnFont=new Font("Arial", Font.BOLD, 20);
dispFont=new Font("TimesRoman", 0, 15);
stopFont=new Font("TimesRoman", Font.BOLD, 16);
Dimension d = size();
offgraphics.setColor(Color.black);
if(lghtOrStp==1){
offgraphics.drawString("Traffic Light Period (1: red, 0: green)", 600,50);
offgraphics.setColor(Color.red);
offgraphics.drawString("red", 714, 50);
offgraphics.setColor(Color.green);
offgraphics.drawString("green", 747, 50);
offgraphics.setColor(Color.black);
for(int k=0; k<3; k++){
int tempred= light[k].redpauss/200, tempgreen= light[k].greenpauss/200;
int temp1=rdright[3]+170;
int temp2, temp3, temp4, temp5;
if (light[k].signal==0){
temp2=temp1+tempred;
temp3=30*(k+1)+40;
temp4= temp2+tempgreen;
temp5=temp3+12;
}
else{
temp2=temp1+tempgreen;
temp3=30*(k+1)+40+12;
temp4= temp2+tempred;
temp5=temp3-12;
}
offgraphics.drawString("Light " +Integer.toString(k+1), temp1-40, (temp5+temp3)/2+5);
while (temp1<d.width){
offgraphics.drawLine(temp1, temp3, temp2, temp3);
offgraphics.drawLine(temp2, temp5, temp4, temp5);
offgraphics.drawLine(temp1, temp3, temp1, temp5);
offgraphics.drawLine(temp2, temp3, temp2, temp5);
temp1=temp4;
temp2=temp1+tempred;
temp4=temp2+tempgreen;
}
}
offgraphics.setColor(Color.lightGray);
offgraphics.fillRect(rdright[3]+328, 30, 15, 130);
offgraphics.setColor(Color.gray);
offgraphics.drawRect(rdright[3]+120, 20, 223, 145);
offgraphics.setColor(Color.black);
}
else{
offgraphics.setFont(warnFont);
offgraphics.setColor(Color.white);
offgraphics.fillOval(rdleft[3]+175, rdtop-160, 70, 70);
offgraphics.setColor(Color.red);
offgraphics.fillOval(rdleft[3]+180, rdtop-155, 60, 60);
offgraphics.setColor(Color.white);
offgraphics.drawString("STOP", rdleft[3]+183, rdtop-116);
offgraphics.setColor(Color.black);
offgraphics.setFont(dispFont);
offgraphics.drawString("(California)", rdleft[3]+185, rdtop-50);
}
}
public void paintLights(Graphics g){
Font dispFont, stopFont;
dispFont=new Font("TimesRoman", 0, 15);
stopFont=new Font("TimesRoman", Font.BOLD, 16);
g.setFont(dispFont);
int lightwidth=15;
for(int k=1; k<4; k++){
if(lghtOrStp==0){
g.setColor(Color.red);
g.fillOval(rdleft[k]-18, rdtop+4, lightwidth, lightwidth);
g.setColor(Color.white);
g.setFont(stopFont);
g.drawString("S", rdleft[k]-14, rdtop+16);
g.setFont(dispFont);
}
else{
g.setColor(Color.black);
g.fillRect(rdleft[k]-18, rdtop+4, lightwidth-2, lightwidth-2);
g.setColor(light[k-1].signal==1 ? Color.red : Color.green);
g.fillOval(rdleft[k]-7, rdtop+6, 6, 9);
g.setColor(light[k-1].signal==1 ? Color.green : Color.red);
g.fillOval(rdleft[k]-16, rdtop+2, 9, 6);
g.setColor(Color.black);
g.drawString("Light "+k, rdleft[k]-58, rdtop+17);
}
}
}
public void paintAxies(Graphics g){
int temp1=610;
int temp2=350;
int temp3=temp1+160;
int temp4= temp2-80;
offgraphics.setColor(Color.gray);
offgraphics.drawRect(rdright[3]+120, temp4-35, 220, 130);
offgraphics.setColor(Color.black);
offgraphics.drawLine(temp1, temp2, temp3, temp2);
offgraphics.drawLine(temp3, temp2, temp3-10, temp2-2);
offgraphics.drawLine(temp3, temp2, temp3-10, temp2+2);
offgraphics.drawLine(temp1, temp2, temp1, temp4);
offgraphics.drawLine(temp1, temp4, temp1-2, temp4+10);
offgraphics.drawLine(temp1, temp4, temp1+2, temp4+10);
for (int k=1; k<4; k++){
int grid=20*k;
offgraphics.drawLine(temp1, temp2- grid, temp1+5, temp2- grid);
offgraphics.drawString(k+".0", temp1- 20, temp2- grid+5);
}
offgraphics.drawString("Time", temp3-10, temp2-10);
offgraphics.drawString("Traffic Flow ", temp1-20, temp2-95);
offgraphics.drawString(" (cars/sec.)", temp1-20, temp2-82);
for (int k=0; k<40; k++){
if (k>=carpermin[0].count){
temp3=1;
offgraphics.setColor(Color.gray);
}
else{
temp3=2;
offgraphics.setColor(Color.black);
}
offgraphics.drawRect(k*3+temp1, temp2 - (int)(carpermin[0].carflow[k]*20+1), temp3, temp3);
}
}
public synchronized void update(Graphics g) {
Dimension d = size();
if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) {
offscreen = createImage(d.width, d.height);
offscreensize = d;
offgraphics = offscreen.getGraphics();
}
offgraphics.setColor(getBackground());
offgraphics.fillRect(0, 0, d.width, d.height);
paintRoad(offgraphics);
//draw lights
paintLights(offgraphics);
//draw light period
paintLghtPeriod(offgraphics);
//draw axies for the flow chart
paintAxies(offgraphics);
//draw cars
for (int i = 0 ; i < nnodes ; i++) {
paintNode(offgraphics, nodes[i]);
}
g.drawImage(offscreen, 0, 0, null);
}
public synchronized boolean mouseDown(Event evt, int x, int y) {
double bestdist = Double.MAX_VALUE;
for (int i = 0 ; i < nnodes ; i++) {
Node n = nodes[i];
double dist = (n.x - x) * (n.x - x) + (n.y - y) * (n.y - y);
if (dist < bestdist) {
pick = n;
pickoldx=n.x;
pickoldy=n.y;
bestdist = dist;
}
}
pick.x = x;
pick.y = y;
repaint();
return true;
}
public synchronized boolean mouseDrag(Event evt, int x, int y) {
pick.x = x;
pick.y = y;
repaint();
return true;
}
public synchronized boolean mouseUp(Event evt, int x, int y) {
boolean insidelane;
pick.x = x;
pick.y = y;
insidelane=false;
for (int k=1; k<4; k++)
if (x>rdleft[k]&&x<rdright[k])
{
pick.road=k;
pick.x=xpos[k-1];
pick.carW= carwidth;
pick.carL= carlength;
insidelane=true;
}
if (!insidelane&&(y<rdtop&&y>rdbottom))
{
pick.road=0;
pick.y=ypos;
pick.carW= carlength;
pick.carL= carwidth;
}
else if(!insidelane)
{
pick.x=pickoldx;
pick.y=pickoldy;
}
pick = null;
repaint();
return true;
}
public void start() {
relaxer = new Thread(this);
relaxer.start();
}
public void stop() {
relaxer.stop();
}
}