1  // (c) NPAC
  2  // Authors: Mehmet Sen, Ozgur Balsoy at NPAC
  3  // 
  4  import java.applet.*;
  5  import java.awt.*;
  6  import java.util.*;
  7  //************************************************************************
  8  // APPLET
  9  //*******************************************************************
 10  
 11  public class GridApplet extends Applet {
 12  
 13      public void init() {
 14  	Label status = new Label("Welcome!", Label.CENTER);
 15  	status.setBackground(Color.pink);
 16  	GridCanvas canvas = new GridCanvas(status,getImage(getDocumentBase(),"grenbull.gif"),getImage(getDocumentBase(),"redbull.gif"));
 17  
 18  	setLayout(new BorderLayout());
 19  
 20  	add("North", new ControlPanel(canvas, status));
 21  	add("Center", canvas);
 22  	add("South", status);
 23        }
 24  }
 25  //************************************************************************
 26  // Control Panel
 27  //*******************************************************************
 28  
 29  class ControlPanel extends Panel {
 30  
 31      int MAXLINES=20;
 32  
 33      GridCanvas canvas;
 34      Label statusLine;
 35      Choice rows, cols;
 36  
 37      public ControlPanel(GridCanvas canvas, Label statusLine) {
 38  	//setBackground(Color.gray);
 39  	//setForeground(Color.yellow);
 40  	
 41  	this.canvas = canvas;
 42  	this.statusLine = statusLine;
 43  
 44  	rows=new Choice();
 45  	cols=new Choice();
 46  	for(int i=1; i<MAXLINES; i++) {
 47  	    rows.addItem(Integer.toString(i));
 48  	    cols.addItem(Integer.toString(i));
 49  	  }
 50  	
 51  	setLayout(new GridLayout(2,4));
 52  
 53  	add(new Label("Rows:  ", Label.RIGHT));
 54  	add(rows);
 55  	add(new Button("New"));
 56  	add(new Button("Graph"));
 57  
 58  	add(new Label("Columns:  ", Label.RIGHT));
 59  	add(cols);
 60  	add(new Button("Check"));
 61  	add(new Button("Back"));
 62        }
 63  
 64      public boolean action(Event evt, Object what) {
 65  
 66  	if(evt.target instanceof Button) {
 67  	    String s=(String)what;
 68  	    statusLine.setText(s);
 69  	    if(s.equals("New")) {
 70  		canvas.draw(rows.getSelectedIndex()+1, 
 71  			    cols.getSelectedIndex()+1);
 72  	      } else if(s.equals("Check")) {
 73  		canvas.check();  
 74  	      } else if(s.equals("Back")) {
 75  		  canvas.back();  
 76  	      }else if(s.equals("Graph")) {
 77  		  canvas.graph();  
 78  	      }
 79  
 80  	    return true;
 81  	  }
 82  	return false;
 83        }
 84  
 85  }
 86  //************************************************************************
 87  // CANVAS
 88  //*******************************************************************
 89  class GridCanvas extends Canvas {
 90      int  GRID=1;
 91      int GRAPH=0;
 92      int displayMode=GRID;
 93      Label statusLine;
 94      double MARGINS = 0.15;
 95      Image ballg;
 96      Image ballr;
 97  
 98      int rows, cols, length;
 99      Point gridCorner;
100      GraphComponent tempComp;
101      GraphComponent[] rowComps, colComps;
102      GridCell[][] cells;
103      boolean gridExist = false;
104  
105      public GridCanvas(Label statusLine,Image ballg,Image ballr) {
106  	this.ballg=ballg;
107  	this.ballr=ballr;
108  	this.statusLine = statusLine;
109        }
110  
111      public void draw(int rows, int cols) {
112  	Graphics g=getGraphics();	
113  	g.drawImage(ballg,-30,-30,null);
114  	g.drawImage(ballr,-60,-60,null);
115  	g.dispose();
116  	// asctual statrt
117  
118  	displayMode=GRID;
119  	statusLine.setText("Drawing " + rows + " by " + cols + " grid.");
120  	cells=new GridCell[rows][cols];
121  
122  	rowComps = new GraphComponent[rows];
123  	for(int i=0; i<rows; i++)
124  	  rowComps[i] = new GraphComponent( i );
125  
126  	colComps = new GraphComponent[cols];
127  	for(int i=0; i<cols; i++)
128  	  colComps[i] = new GraphComponent( i );
129  
130  	int width = (int)(size().width * (1.0 - MARGINS * 2.0));
131  	int height = (int)(size().height * (1.0 - MARGINS * 2.0));
132  	length = Math.min( width / cols, height / rows);
133  
134  	gridCorner=new Point((size().width - length * cols) / 2,
135  			     (size().height - length * rows) / 2);
136  
137  	for(int r=0; r<rows; r++) 
138  	  for(int c=0; c<cols; c++)
139  	    cells[r][c] = new GridCell(gridCorner.x + c * length,
140  				       gridCorner.y + r * length, 
141  				       length, r, c );
142  	this.rows = rows;
143  	this.cols = cols;
144  	gridExist = true;
145  	repaint();
146        }
147  
148      public GraphComponent calculateComponent(){
149  	GraphComponent[] comp=new GraphComponent[cols];
150  	for(int c=0; c<cols; c++) {
151  	  comp[c]=new GraphComponent(colComps[c]);
152  	}
153  	for(int r=0; r<rows; r++) {   // finds individual components
154  	    Vector v=rowComps[r].getCells();
155  	    if(!v.isEmpty()) {
156  		GridCell c=(GridCell)(v.firstElement());
157  		for(Enumeration e=rowComps[r].getCells().elements(); e.hasMoreElements(); ) {
158  
159  		    GridCell cell= (GridCell)(e.nextElement());
160  
161  		    int firstElementID = comp[c.colIndex].ID;
162  		    int currentCellID = comp[cell.colIndex].ID;
163  		    
164  		    comp[c.colIndex].merge(comp[cell.colIndex]);
165  
166  		    int greatID = Math.max(firstElementID, currentCellID  );
167  
168  		    for(int j=0; j<cols; j++)
169  		      if(comp[j].ID == greatID) 
170  			if( firstElementID < currentCellID ) 
171  			  comp[j] = comp[c.colIndex];
172  			else
173  			  comp[j] = comp[cell.colIndex];
174  		  }
175  	      }
176  	}
177  	for(int i=0;i<cols;i++)
178  	    if ( !comp[i].getCells().isEmpty()) {
179  		return comp[i];
180  	    }
181  	return null;
182      }
183      
184      public void check(){
185  	if ( !gridExist ) {
186  	    statusLine.setText("Check :    Please define the grid first!");
187  	    return;
188  	}
189  	
190  	displayMode=GRID;
191          this.tempComp=calculateComponent();
192  	Graphics g=getGraphics();
193  	for(int k=0; k<5; k++) {
194  	    animate(tempComp,k*3);
195  	    paint(g);
196  	//    try {
197  		//Thread.sleep(200);
198  	  //    }
199  	  //  catch(InterruptedException e) {};
200  	  }
201  	g.dispose(); 
202  	// check the rigidity 
203  	if (tempComp==null) {
204  	    statusLine.setText("NOT rigid !");
205  	    return;
206  	}
207  	int[] c= new int[cols];
208  	int[] r= new int[rows];
209  	Vector v=tempComp.getCells();
210  	int total=0;
211  	
212  	for(int i=0;i<v.size();i++){
213  	    GridCell cell=(GridCell)v.elementAt(i);
214  	    if ( c[cell.colIndex]==0){
215  		c[cell.colIndex]=1;
216  		total++;
217  	    }
218  	    if ( r[cell.rowIndex]==0){
219  		r[cell.rowIndex]=1;
220  		total++;
221  	    }
222  	}
223  	if (total==(cols+rows))
224  	    statusLine.setText("RIGID");
225          else statusLine.setText("NOT rigid");
226      }
227  
228      public boolean searchRigid(GraphComponent gc, GraphComponent rigidSource){
229  	for (Enumeration e=rigidSource.getCells().elements(); e.hasMoreElements();)
230  	  if ( gc.getCells().contains( e.nextElement() )) 
231  	    return true;
232  	return false;
233        }
234  	
235  
236      public void animate(GraphComponent gc,int angle){
237  
238  
239  	cells[0][0].updateAngle(angle);
240  	cells[0][0].place(gridCorner);
241  	
242  	if ( searchRigid(gc,rowComps[0]) )
243  	  cells[0][0].rotateLeft(null);
244  
245  	if (searchRigid(gc,colComps[0]) )
246  	  cells[0][0].rotateTop(null);
247  
248  	
249  	for(int i=1; i<cols; i++)
250  	  if ( (gc == null && i%2==1) || searchRigid(gc,colComps[i]) )
251  	    cells[0][i].rotateTop(cells[0][i-1]);
252  	  else cells[0][i].translateTop(cells[0][i-1]);
253  	  
254  	for(int i=1; i<rows; i++)
255  	  if ( (gc == null && i%2==1) || searchRigid(gc,rowComps[i])   )
256  	    cells[i][0].rotateLeft(cells[i-1][0]);
257  	  else cells[i][0].translateLeft(cells[i-1][0]);
258  	
259  	GridCell below, corner, right;
260  	for(int m=0; m<rows; m++) 
261  	  for(int n=0; n<cols; n++) {
262  	      if( m < rows-1) below=cells[m+1][n];
263  	      else  below=null; 
264  
265  	      if( n < cols-1) right=cells[m][n+1];
266  	      else  right=null; 
267  
268  	      if ( below==null || right == null ) corner = null;
269  	      else corner=cells[m+1][n+1];
270  
271  	      cells[m][n].finish(below,right,corner);
272  	    }
273  	cells[0][0].findShifting(size().height/2,rows*cols);
274  	for(int m=0; m<rows; m++) 
275  	    for(int n=0; n<cols; n++) 
276  		cells[m][n].shift();
277        }
278      public void back()
279      {  	if ( !gridExist ) {
280  	    statusLine.setText("Back :   Please define the grid first!");
281  	    return;
282  	}
283  	displayMode=GRID;
284  	Graphics g=getGraphics();
285  	for(int k=4; k>-1; k--) {
286  	    animate(tempComp,k*3);
287  	    paint(g);
288  	//    try {
289  		//Thread.sleep(200);
290  	  //    }
291  	  //  catch(InterruptedException e) {};
292  	  }
293  	g.dispose();
294      }
295      
296  
297      public boolean mouseDown(Event evt, int x, int y) {
298  	if ( !gridExist || displayMode==GRAPH)
299  	  return true;
300  	//x -= gridCorner.x;
301  	//y -= gridCorner.y;
302  	//if(x<(gridCorner.x+length*cols) && y<(gridCorner.y+length*rows) 
303  	//   && x>gridCorner.x && y>gridCorner.y ) {
304  	    int i,c=-1; //= x / length;
305  	    int j,r=-1;//= y / length;
306  	   
307  	    for (i=0;i<rows;i++)
308  		for (j=0;j<cols;j++) 
309  		    if ( cells[i][j].myframe().inside(x,y)) {
310  			r=i;
311  			c=j;
312  			break;
313  		    }
314  	    if ( r==-1 ) return true;
315  	    
316  	    cells[r][c].toggleRigid();
317  	    Graphics g=getGraphics();
318  	    cells[r][c].paint(g);
319  	    g.dispose();
320  
321  	    if(cells[r][c].rigid) {
322  		rowComps[r].addCell(cells[r][c]);
323  		colComps[c].addCell(cells[r][c]);
324  	      } else {
325  		  rowComps[r].removeCell(cells[r][c]);
326  		  colComps[c].removeCell(cells[r][c]);
327  		}
328  	//  }
329  	return true;
330        }
331      public void graph()    {
332  	displayMode=GRAPH;
333  	this.tempComp=calculateComponent();
334  	repaint();
335  	repaint();
336      }
337      public void plotGraph(Graphics g)
338      {
339  	
340  	int colonsY = (int)(size().height * ( MARGINS ));
341  	int rowsY = (int)(size().height * (1.0 - MARGINS ));
342  	int stepY = (int)(size().height * ( .08 ));
343  	int stepX = (int)(size().width * ( .05 ));
344  	int X = (int)(size().width/2);
345          if ( rows > cols )  X -=stepX*rows/2;
346  	else X -=stepX*cols/2;
347  	
348  	for (int i=0;i<rows;i++)
349  	    for (int j=0;j<cols;j++)
350  		if ( rowComps[i].getCells().contains( cells[i][j] ) &&
351  		     colComps[j].getCells().contains( cells[i][j] ) )  {
352  		    if ( tempComp.getCells().contains( cells[i][j] ))
353  			g.setColor(Color.red);
354  		    else g.setColor(Color.black);
355  		    g.drawLine(X+i*stepX+8,rowsY-3*stepY+8,
356  			       X + j*stepX+8,  colonsY+2*stepY+8);
357  		}
358  	g.setColor(Color.black);
359  	g.drawString ("COLONS",X+stepX*cols/2 -40,colonsY);
360  	for (int j=0; j < cols ;j++) {
361  	    g.drawString(Integer.toString(j+1),X + j*stepX,colonsY+stepY);
362  	    g.drawImage(ballg,X + j*stepX,colonsY+2*stepY,null);
363  	}
364  	
365  	for (int i=0; i < rows ;i++){
366  	    g.drawString(Integer.toString(i+1),X + i*stepX,rowsY-stepY);
367  	    g.drawImage(ballr,X + i*stepX,rowsY-3*stepY,null);
368  	}
369  	g.drawString ("ROWS",X+stepX*rows/2 -15,rowsY);
370  	
371      }
372      
373  
374      public void update(Graphics g) {
375  	paint(g);
376        }
377  
378      public void paint(Graphics g) {
379  
380  	// draw a rectangle inside canvas to separate canvas from buttons.
381  	g.clearRect(6, 6, size().width-6, size().height-6);
382  	g.setColor(Color.yellow);
383  	g.fillRect(0,0,size().width-1,4);
384  	g.fillRect(0,0,4,size().height-1);
385  	g.fillRect(size().width-4,0,4,size().height-1);
386  	g.fillRect(0,size().height-4,size().width-1,4);
387  	g.setColor(Color.black);
388  	g.drawRect(5,5,size().width-11, size().height-11);
389  	if(gridExist)
390  	    if ( displayMode == GRID )
391  		for(int m=0; m<rows; m++) 
392  		    for(int n=0; n<cols; n++)
393  			cells[m][n].paint(g);
394  	    else if ( displayMode == GRAPH ) plotGraph(g);
395        }
396  }
397  // canvas ends here
398  //****************************************************************************
399  //CELL
400  //****************************************************************************
401  class GridCell {
402  
403      Point topLeft, topRight, bottomLeft, bottomRight;
404      public int rowIndex, colIndex;
405      public boolean rigid = false;
406      static int length;
407    double diagonal;
408      static double COS= 0.9961947, SIN = 0.087155743; // cos(5) , sin(5)
409      static double angle =0.0;  
410      static int centery,deltay=0;
411      
412      public GridCell(int x, int y, int length, int rowIndex, int colIndex) {
413  
414  	  topLeft  = new Point(x, y);
415  	  topRight = new Point(x + length, y);
416  
417  	  bottomLeft  = new Point(x, y + length);
418  	  bottomRight = new Point(x + length, y + length);
419  	  
420  	  this.length=length;
421  	  this.diagonal=Math.sqrt(2*length*length);
422  	  this.rowIndex = rowIndex;
423  	  this.colIndex = colIndex;
424        }
425      public void place(Point p) 
426        {   
427  	  topLeft.x=p.x;
428  	  topLeft.y=p.y;
429  	  topRight.x=p.x+length;
430  	  topRight.y=p.y;
431  	  bottomLeft.x =p.x;
432  	  bottomLeft.y =p.y+length;
433  	  bottomRight.x = p.x+length;
434  	  bottomRight.y = p.y+length;   
435  	  centery=0;
436  	  deltay=0;
437  	  
438        }
439      
440  	
441      public void updateAngle(int angle){
442  	//if ( angle >= 15.0 )
443  	//  angle=0.0;
444  	//angle +=3.0;
445  	this.angle=angle;
446  	
447  	COS= Math.cos((angle*Math.PI)/180.0);
448  	SIN= Math.sin((angle*Math.PI)/180.0);
449        }
450  
451      public void toggleRigid() {
452  	rigid = !rigid;
453        }
454      public void rotateTop(GridCell neighbor){
455         	if (neighbor!=null) {
456  	    topLeft.x=neighbor.topRight.x; 
457  	    topLeft.y=neighbor.topRight.y;
458  	}
459  	
460  	topRight.x =(int)(topLeft.x +(double)length*COS);
461  	topRight.y =(int)(topLeft.y -(double)length*SIN);
462        }
463      public void rotateLeft(GridCell neighbor){
464         	if (neighbor!=null) {
465  	    topLeft.x=neighbor.bottomLeft.x;
466  	    topLeft.y=neighbor.bottomLeft.y;
467  	}
468  	
469  	bottomLeft.x = (int) (topLeft.x +(double)length*SIN);
470  	bottomLeft.y = (int) (topLeft.y +(double)length*COS);
471        }
472      public void translateTop(GridCell neighbor){
473         	if (neighbor!=null) {
474  	    topLeft.x=neighbor.topRight.x;
475  	    topLeft.y=neighbor.topRight.y;
476  	}
477  	
478  	topRight.x =topLeft.x +length;
479  	topRight.y =topLeft.y;
480        }
481      public void translateLeft(GridCell neighbor){
482         	if (neighbor!=null) {
483  	   topLeft.x=neighbor.bottomLeft.x; 
484  	   topLeft.y=neighbor.bottomLeft.y;
485  	}
486  	
487  	bottomLeft.x =topLeft.x ;
488  	bottomLeft.y =topLeft.y +length;
489        }
490      
491      public void finish(GridCell below,GridCell right, GridCell corner){
492  	bottomRight.x= bottomLeft.x + (topRight.x-topLeft.x);
493  	bottomRight.y= bottomLeft.y + (topRight.y-topLeft.y);
494  	
495  	if ( below != null ) {
496  	    below.topRight.x = this.bottomRight.x; 
497  	    below.topRight.y = this.bottomRight.y; 
498  	}
499  	if ( right != null ){ 
500  	    right.bottomLeft.x = this.bottomRight.x;
501  	    right.bottomLeft.y = this.bottomRight.y;
502  	}
503  	
504  	if ( corner != null ) { 
505  	    corner.topLeft.x= this.bottomRight.x;
506  	    corner.topLeft.y= this.bottomRight.y;
507  	}
508  	
509  	centery += bottomRight.y+bottomLeft.y+topRight.y +topLeft.y;
510  	
511  
512        }
513      public void shift(){
514  	topLeft.y += deltay;
515  	bottomLeft.y += deltay;
516  	bottomRight.y += deltay;
517  	topRight.y += deltay;
518      }
519      public void findShifting(int originy,int n )  // how many cells
520       {
521  	 centery =centery/( 4*n);
522  	 deltay=originy-centery;
523      }
524      public Polygon myframe()
525      {
526  	Polygon frame=new Polygon();
527  	frame.addPoint(topLeft.x,topLeft.y);
528  	frame.addPoint(bottomLeft.x,bottomLeft.y);
529  	frame.addPoint(bottomRight.x,bottomRight.y);
530  	frame.addPoint(topRight.x,topRight.y);
531  	frame.addPoint(topLeft.x,topLeft.y);
532  	return frame;
533      }
534      
535  	
536  
537      public void paint(Graphics g) {
538  	
539  	Polygon frame=myframe();
540  	if(rigid) { 
541  	  ///  g.setColor(Color.red);
542  	  /// g.fillPolygon(frame);
543  	    //	    BrickMe(g); 
544  	    BraceMeFromRight(g);
545  	    BraceMeFromLeft(g);
546  
547  	  } else {
548  	      g.setColor(Color.lightGray);
549  	      g.fillPolygon(frame);
550  	    }
551  	g.setColor(Color.black);
552  	g.drawPolygon(frame);
553        }
554      public void BraceMeFromLeft(Graphics g){
555        int[] x=new int[4];
556        int[] y=new int[4];
557        g.setColor(Color.black);
558        g.drawLine(topLeft.x,topLeft.y,bottomRight.x,bottomRight.y);
559        double longDiagonal=Math.sqrt( (topLeft.x- bottomRight.x) *  (topLeft.x-bottomRight.x) +
560                                     (topLeft.y- bottomRight.y)*(topLeft.y-bottomRight.y));
561        double rate=1.0 - (double)(diagonal)*.90/(double)longDiagonal ;
562        rate/=2.0;
563  
564        if (rate < 0.0) rate=0.0;
565  
566  
567        int x1= (int)  (topLeft.x +(-topLeft.x+ bottomRight.x)*rate);
568        int y1= (int)  (topLeft.y + (-topLeft.y+ bottomRight.y)*rate);
569        int x2= (int)  (bottomRight.x +  ( topLeft.x- bottomRight.x)*rate);
570        int y2= (int)  (bottomRight.y +  ( topLeft.y-bottomRight.y)*rate);
571        g.setColor(Color.yellow);
572        x[0]=x1+2; y[0]=y1;
573        x[1]=x2; y[1]=y2-3;
574        x[2]=x2-2; y[2]=y2;
575        x[3]=x1; y[3]=y1+3;
576        g.fillPolygon(x,y,4);
577        //      g.drawLine(x1,y1,x2,y2);
578  //      g.drawLine(x1+1,y1,x2+1,y2);g.drawLine(x1,y1+1,x2,y2+1);
579  
580      }
581      public void BraceMeFromRight(Graphics g){
582  	int[] x=new int[4];
583  	int[] y=new int[4];
584  
585  	g.setColor(Color.black);
586  	g.drawLine(topRight.x,topRight.y,bottomLeft.x,bottomLeft.y);
587  
588  	double longDiagonal=Math.sqrt( (bottomLeft.x- topRight.x) *  (bottomLeft.x-topRight.x) +
589                                        (bottomLeft.y- topRight.y)*(bottomLeft.y-topRight.y));
590  	double rate=1.0 - (double)diagonal*.90/(double)longDiagonal ;
591  	rate/=2.0;
592  	if (rate < 0.0) rate=0.0;
593  	int x1= (int)  (bottomLeft.x +(-bottomLeft.x+ topRight.x)*rate);
594  	int y1= (int)   (bottomLeft.y + (-bottomLeft.y+ topRight.y)*rate);
595  	int x2= (int)  (topRight.x +  ( bottomLeft.x- topRight.x)*rate);
596  	int y2=  (int)  (topRight.y +  ( bottomLeft.y-topRight.y)*rate);
597  	x[0]=x1+3; y[0]=y1;
598  	x[1]=x2; y[1]=y2+3;
599  	x[2]=x2-2; y[2]=y2;
600  	x[3]=x1; y[3]=y1-2;
601  
602  	g.setColor(Color.cyan);
603  	g.fillPolygon(x,y,4);
604  
605  /*      g.drawLine(x1,y1,x2,y2);
606        g.drawLine(x1+1,y1,x2+1,y2);g.drawLine(x1,y1+1,x2,y2+1);
607        */
608      }
609  
610      public void BrickMe(Graphics g){
611  
612      g.setColor(Color.black);
613  
614      Point topMid = new Point((topRight.x+topLeft.x)/2,(topRight.y+topLeft.y)/2);
615      Point bottomMid = new Point((bottomRight.x+bottomLeft.x)/2,(bottomRight.y+bottomLeft.y)/2);
616      Point leftMid = new Point((topLeft.x+bottomLeft.x)/2,(bottomLeft.y+topLeft.y)/2);
617      Point rightMid = new Point((bottomRight.x+topRight.x)/2,(bottomRight.y+topRight.y)/2);
618      Point mid =new Point((leftMid.x+rightMid.x)/2, (rightMid.y+leftMid.y)/2);
619      
620      Point closeTopLeft = new Point((topLeft.x+leftMid.x)/2,(topLeft.y+leftMid.y)/2);
621      Point closeBottomLeft = new Point((leftMid.x+bottomLeft.x)/2,(leftMid.y+bottomLeft.y)/2);
622      Point closeTopRight = new Point((topRight.x+rightMid.x)/2,(topRight.y+rightMid.y)/2);
623      Point closeBottomRight = new Point((rightMid.x+bottomRight.x)/2,(rightMid.y+bottomRight.y)/2);
624  
625      Point closeTopMid = new Point ( (closeTopLeft.x + closeTopRight.x)/2, (closeTopLeft.y + closeTopRight.y)/2);
626      Point closeBottomMid= new Point ( (closeBottomLeft.x + closeBottomRight.x)/2, (closeBottomLeft.y + closeBottomRight.y)/2);
627      
628      Point closeTopCloseLeft  = new Point( (closeTopLeft.x+closeTopMid.x)/2, (closeTopLeft.y+closeTopMid.y)/2);
629      Point closeTopCloseRight = new Point( (closeTopRight.x+closeTopMid.x)/2, (closeTopRight.y+closeTopMid.y)/2);
630      Point closeBottomCloseLeft = new Point( (closeBottomLeft.x+closeBottomMid.x)/2, (closeBottomLeft.y+closeBottomMid.y)/2);
631      Point closeBottomCloseRight = new Point( (closeBottomRight.x+closeBottomMid.x)/2, (closeBottomRight.y+closeBottomMid.y)/2);
632  
633      Point closeLeftMid =new Point ( (leftMid.x+mid.x)/2, (leftMid.y+mid.y)/2);
634      Point closeRightMid =new Point ( (rightMid.x+mid.x)/2, (rightMid.y+mid.y)/2);
635      
636      Point bottomCloseLeft = new Point ( (bottomLeft.x+bottomMid.x)/2 , (bottomLeft.y+bottomMid.y)/2);
637      Point bottomCloseRight= new Point ( (bottomRight.x+bottomMid.x)/2 , (bottomRight.y+bottomMid.y)/2);
638      
639      g.drawLine ( closeTopLeft.x,closeTopLeft.y,closeTopRight.x,closeTopRight.y);
640      g.drawLine ( closeBottomLeft.x,closeBottomLeft.y,closeBottomRight.x,closeBottomRight.y );
641      g.drawLine ( leftMid.x,leftMid.y,rightMid.x,rightMid.y);
642      
643      g.drawLine ( topMid.x,topMid.y,closeTopMid.x,closeTopMid.y );
644      
645      g.drawLine ( closeTopCloseLeft.x,closeTopCloseLeft.y,closeLeftMid.x,closeLeftMid.y );
646      g.drawLine ( closeTopCloseRight.x,closeTopCloseRight.y,closeRightMid.x,closeRightMid.y );
647      
648      g.drawLine ( mid.x,mid.y,closeBottomMid.x,closeBottomMid.y);
649      
650      g.drawLine ( bottomCloseLeft.x,bottomCloseLeft.y,closeBottomCloseLeft.x,closeBottomCloseLeft.y );
651      g.drawLine ( bottomCloseRight.x,bottomCloseRight.y,closeBottomCloseRight.x,closeBottomCloseRight.y );
652    }
653  }
654  // cell ends here
655  //****************************************************************************
656  // COMPONENT
657  //****************************************************************************
658  class GraphComponent {
659  
660      Vector cells;
661      public int ID;
662  
663      public GraphComponent(int ID) {
664  	this.ID = ID;
665  	cells = new Vector();
666        }
667  
668      public GraphComponent(GraphComponent gc) {
669  	this.ID = gc.ID;
670  	cells = new Vector();
671  	for(Enumeration e=gc.getCells().elements(); e.hasMoreElements(); )
672  	          addCell((GridCell)(e.nextElement()));
673        }
674  
675      public void addCell(GridCell cell) {
676  	cells.addElement(cell);
677        }
678      
679      public void removeCell(GridCell cell) {
680  	cells.removeElement(cell);
681        }
682  
683      public Vector getCells() {
684  	return cells;
685        }
686  
687      public void listCells() {
688  	for(Enumeration e=cells.elements(); e.hasMoreElements(); ) {
689  	    GridCell cell=(GridCell)(e.nextElement());
690  	    System.out.print("("+cell.rowIndex + "," + cell.colIndex + ")");
691  	  }
692  	System.out.println(" ");
693        }
694  
695      public void merge(GraphComponent comp) {
696  	if(comp.ID == this.ID) return;
697  	if(comp.ID < this.ID) comp.merge(this);
698  	else for(Enumeration e=comp.getCells().elements(); e.hasMoreElements(); )
699  	          addCell((GridCell)(e.nextElement()));
700        }
701    }