lib/browser/GraphBrowser/Graph.java
author berghofe
Wed, 07 Jul 2010 18:17:23 +0200
changeset 37737 7bf3ec9e7b0c
parent 33686 8e33ca8832b1
child 51488 ca4088bf8365
permissions -rw-r--r--
Boxes may now have different widths.
berghofe@3599
     1
/***************************************************************************
berghofe@3599
     2
  Title:      GraphBrowser/Graph.java
berghofe@3599
     3
  Author:     Stefan Berghofer, TU Muenchen
berghofe@3599
     4
berghofe@3599
     5
  This class contains the core of the layout algorithm and methods for
berghofe@3599
     6
  drawing and PostScript output.
berghofe@3599
     7
***************************************************************************/
berghofe@3599
     8
berghofe@3599
     9
package GraphBrowser;
berghofe@3599
    10
berghofe@3599
    11
import java.util.*;
berghofe@3599
    12
import java.awt.*;
berghofe@3599
    13
import java.io.*;
berghofe@3599
    14
berghofe@3599
    15
public class Graph {
berghofe@3599
    16
	/**** parameters for layout ****/
berghofe@3599
    17
berghofe@3599
    18
	public int box_height=0;
berghofe@3599
    19
	public int box_height2;
berghofe@37737
    20
	public Graphics gfx;
berghofe@3599
    21
berghofe@3599
    22
	Vector vertices=new Vector(10,10);
berghofe@3599
    23
	Vector splines=new Vector(10,10);
berghofe@3599
    24
	Vector numEdges=new Vector(10,10);
berghofe@3599
    25
	Vertex []vertices2;
berghofe@3599
    26
berghofe@3599
    27
	public int min_x=0,min_y=0,max_x=10,max_y=10;
berghofe@3599
    28
berghofe@3599
    29
	/********************************************************************/
berghofe@3599
    30
	/*                         clone graph object                       */
berghofe@3599
    31
	/********************************************************************/
berghofe@3599
    32
berghofe@3599
    33
	public Object clone() {
berghofe@3599
    34
		Graph gr=new Graph();
berghofe@3599
    35
		Enumeration e1;
berghofe@3599
    36
		int i;
berghofe@3599
    37
berghofe@3599
    38
		gr.splines=(Vector)(splines.clone());
berghofe@3599
    39
berghofe@3599
    40
		e1=vertices.elements();
berghofe@3599
    41
		while (e1.hasMoreElements())
berghofe@3599
    42
			gr.addVertex((Vertex)(((Vertex)(e1.nextElement())).clone()));
berghofe@3599
    43
berghofe@3599
    44
		for (i=0;i<vertices.size();i++) {
berghofe@3599
    45
			Vertex vx1=(Vertex)(gr.vertices.elementAt(i));
berghofe@3599
    46
			e1=((Vertex)(vertices.elementAt(i))).getChildren();
berghofe@3599
    47
			while (e1.hasMoreElements()) {
berghofe@3599
    48
				Vertex vx2=(Vertex)(gr.vertices.elementAt(vertices.indexOf(e1.nextElement())));
berghofe@3599
    49
				vx1.addChild(vx2);
berghofe@3599
    50
			}
berghofe@3599
    51
		}
berghofe@3599
    52
berghofe@3599
    53
		gr.vertices2 = new Vertex[vertices.size()];
berghofe@3599
    54
		gr.vertices.copyInto(gr.vertices2);
berghofe@3599
    55
berghofe@3599
    56
		gr.min_x=min_x;gr.max_x=max_x;
berghofe@3599
    57
		gr.min_y=min_y;gr.max_y=max_y;
berghofe@3599
    58
berghofe@3599
    59
		return gr;
berghofe@3599
    60
	}
berghofe@3599
    61
berghofe@3599
    62
	Graph() {}
berghofe@3599
    63
berghofe@3599
    64
	/********************************************************************/
berghofe@3599
    65
	/*                      Read graph from stream                      */
berghofe@3599
    66
	/********************************************************************/
berghofe@3599
    67
berghofe@3599
    68
	public Graph(InputStream s,TreeNode tn) throws IOException, ParseError {
berghofe@6541
    69
		StreamTokenizer tok=new StreamTokenizer(new InputStreamReader(s));
berghofe@3599
    70
		String name,dir,vertexID;
berghofe@3599
    71
		Vertex ve1,ve2;
berghofe@3599
    72
		boolean children,unfoldDir;
berghofe@3599
    73
		int index=0;
berghofe@3599
    74
berghofe@3599
    75
		tok.nextToken();
berghofe@3599
    76
		while (tok.ttype!=StreamTokenizer.TT_EOF) {
berghofe@3599
    77
			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
berghofe@3599
    78
				throw new ParseError("expected: vertex name\nfound   : "+tok.toString());
berghofe@3599
    79
			name=tok.sval;
berghofe@3599
    80
                        tok.nextToken();
berghofe@3599
    81
			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
berghofe@3599
    82
				throw new ParseError("expected: vertex identifier\nfound   : "+tok.toString());
berghofe@3599
    83
			vertexID=tok.sval;
berghofe@3599
    84
			tok.nextToken();
berghofe@3599
    85
			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
berghofe@3599
    86
				throw new ParseError("expected: directory name\nfound   : "+tok.toString());
berghofe@3599
    87
			dir=tok.sval;
berghofe@3599
    88
			tok.nextToken();
berghofe@3599
    89
			if (tok.ttype=='+') {
berghofe@3599
    90
				unfoldDir=true;
berghofe@3599
    91
				tok.nextToken();
berghofe@3599
    92
			} else
berghofe@3599
    93
				unfoldDir=false;
berghofe@3599
    94
			if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
berghofe@3599
    95
				throw new ParseError("expected: path name\nfound   : "+tok.toString());
berghofe@3599
    96
			ve1=findVertex(vertexID);
berghofe@3599
    97
			if (ve1==null) {
berghofe@3599
    98
				ve1=new NormalVertex("");
berghofe@3599
    99
				ve1.setID(vertexID);
berghofe@3599
   100
				ve1.setNumber(index++);
berghofe@3599
   101
				addVertex(ve1);
berghofe@3599
   102
			}
berghofe@3599
   103
			ve1.setPath(tok.sval);
berghofe@3599
   104
			ve1.setDir(dir);
berghofe@3599
   105
                        ve1.setLabel(name);
berghofe@3599
   106
			tn.insertNode(name,dir,tok.sval,ve1.getNumber(),unfoldDir);
berghofe@3599
   107
			tok.nextToken();
berghofe@3599
   108
			if (tok.ttype=='<') {
berghofe@3599
   109
				children=true;
berghofe@3599
   110
				tok.nextToken();
berghofe@3599
   111
			} else if (tok.ttype=='>') {
berghofe@3599
   112
					children=false;
berghofe@3599
   113
					tok.nextToken();
berghofe@3599
   114
			} else children=true;
berghofe@3599
   115
			while (tok.ttype!=';') {
berghofe@3599
   116
				if (tok.ttype!=StreamTokenizer.TT_WORD && tok.ttype!='"')
berghofe@3599
   117
					throw new ParseError("expected: child vertex identifier or ';'\nfound   : "+tok.toString());				
berghofe@3599
   118
				ve2=findVertex(tok.sval);
berghofe@3599
   119
				if (ve2==null) {
berghofe@3599
   120
					ve2=new NormalVertex("");
berghofe@3599
   121
					ve2.setID(tok.sval);
berghofe@3599
   122
					ve2.setNumber(index++);
berghofe@3599
   123
					addVertex(ve2);
berghofe@3599
   124
				}
berghofe@3599
   125
				if (children)
berghofe@3599
   126
					ve1.addChild(ve2);
berghofe@3599
   127
				else
berghofe@3599
   128
					ve1.addParent(ve2);
berghofe@3599
   129
				tok.nextToken();
berghofe@3599
   130
			}
berghofe@3599
   131
			tok.nextToken();
berghofe@3599
   132
		}
berghofe@3599
   133
		vertices2 = new Vertex[vertices.size()];
berghofe@3599
   134
		vertices.copyInto(vertices2);
berghofe@3599
   135
	}
berghofe@3599
   136
	
berghofe@3599
   137
	/*** Find vertex with identifier vertexID ***/
berghofe@3599
   138
berghofe@3599
   139
	public Vertex findVertex(String vertexID) {
berghofe@3599
   140
		Enumeration e1=vertices.elements();
berghofe@3599
   141
		Vertex v1;
berghofe@3599
   142
berghofe@3599
   143
		while (e1.hasMoreElements()) {
berghofe@3599
   144
			v1=(Vertex)(e1.nextElement());
berghofe@3599
   145
			if ((v1.getID()).equals(vertexID))
berghofe@3599
   146
				return v1;
berghofe@3599
   147
		}
berghofe@3599
   148
		return null;
berghofe@3599
   149
	}
berghofe@3599
   150
		 
berghofe@3599
   151
	public void addVertex(Vertex v) {
berghofe@3599
   152
		vertices.addElement(v);
berghofe@3599
   153
		v.setGraph(this);
berghofe@3599
   154
	}
berghofe@3599
   155
berghofe@3599
   156
	public void removeVertex(Vertex v) {
berghofe@3599
   157
		vertices.removeElement(v);
berghofe@3599
   158
	}
berghofe@3599
   159
berghofe@3599
   160
	public Enumeration getVertices() {
berghofe@3599
   161
		return vertices.elements();
berghofe@3599
   162
	}
berghofe@3599
   163
berghofe@3599
   164
	/********************************************************************/
berghofe@3599
   165
	/*                          graph layout                            */
berghofe@3599
   166
	/********************************************************************/
berghofe@3599
   167
berghofe@3599
   168
	public void layout(Graphics g) {
berghofe@3599
   169
		splines.removeAllElements();
berghofe@3599
   170
		hasseDiagram();
berghofe@3599
   171
		Vector layers=min_crossings(insert_dummies((Vector)(sort().elementAt(0))));
berghofe@3599
   172
		setParameters(g);
berghofe@3599
   173
		init_coordinates(layers);
berghofe@3599
   174
		pendulum(layers);
berghofe@3599
   175
		rubberband(layers);
berghofe@3599
   176
		calcSplines(layers);
berghofe@3599
   177
		calcBoundingBox();
berghofe@3599
   178
	}
berghofe@3599
   179
berghofe@3599
   180
	/********************************************************************/
berghofe@3599
   181
	/*                      set layout parameters                       */
berghofe@3599
   182
	/********************************************************************/
berghofe@3599
   183
berghofe@3599
   184
	public void setParameters(Graphics g) {
berghofe@3599
   185
		Enumeration e1=vertices.elements();
berghofe@37737
   186
		int h;
berghofe@37737
   187
		h=Integer.MIN_VALUE;
berghofe@3599
   188
berghofe@3599
   189
		while (e1.hasMoreElements()) {
kleing@13968
   190
		  Box dim=((Vertex)(e1.nextElement())).getLabelSize(g);
berghofe@3599
   191
			h=Math.max(h,dim.height);
berghofe@3599
   192
		}
berghofe@3599
   193
		box_height=h+4;
berghofe@3599
   194
		box_height2=box_height/2;
berghofe@37737
   195
		gfx=g;
berghofe@3599
   196
	}
berghofe@3599
   197
berghofe@3599
   198
	/********************************************************************/
berghofe@3599
   199
	/*                       topological sorting                        */
berghofe@3599
   200
	/********************************************************************/
berghofe@3599
   201
berghofe@3599
   202
	public Vector sort() {
berghofe@3599
   203
		Vector todo=(Vector)(vertices.clone());
berghofe@3599
   204
		Vector layers=new Vector(10,10);
berghofe@3599
   205
		Vector todo2;
berghofe@3599
   206
		Enumeration e1,e2;
berghofe@3599
   207
		Vertex v,v2;
berghofe@3599
   208
berghofe@3599
   209
		e1=vertices.elements();
berghofe@3599
   210
		while (e1.hasMoreElements())
berghofe@3599
   211
			((Vertex)(e1.nextElement())).setDegree(0);
berghofe@3599
   212
berghofe@3599
   213
		e1=vertices.elements();
berghofe@3599
   214
		while (e1.hasMoreElements()) {
berghofe@3599
   215
			v=(Vertex)(e1.nextElement());
berghofe@3599
   216
			e2=v.getChildren();
berghofe@3599
   217
			while (e2.hasMoreElements()) {
berghofe@3599
   218
				v2=(Vertex)(e2.nextElement());
berghofe@3599
   219
				todo.removeElement(v2);
berghofe@3599
   220
				v2.setDegree(1+v2.getDegree());
berghofe@3599
   221
			}
berghofe@3599
   222
		}
berghofe@3599
   223
		while (!todo.isEmpty()) {
berghofe@3599
   224
			layers.addElement(todo);
berghofe@3599
   225
			todo2=new Vector(10,10);
berghofe@3599
   226
			e1=todo.elements();
berghofe@3599
   227
			while (e1.hasMoreElements()) {
berghofe@3599
   228
				e2=((Vertex)(e1.nextElement())).getChildren();
berghofe@3599
   229
				while (e2.hasMoreElements()) {
berghofe@3599
   230
					v=(Vertex)(e2.nextElement());
berghofe@3599
   231
					v.setDegree(v.getDegree()-1);
berghofe@3599
   232
					if (v.getDegree()==0) {
berghofe@3599
   233
						todo2.addElement(v);
berghofe@3599
   234
						v.setDegree(layers.size());
berghofe@3599
   235
					}
berghofe@3599
   236
				}
berghofe@3599
   237
			}
berghofe@3599
   238
			todo=todo2;
berghofe@3599
   239
		}
berghofe@3599
   240
		return layers;
berghofe@3599
   241
	}
berghofe@3599
   242
berghofe@3599
   243
	/********************************************************************/
berghofe@3599
   244
	/*                      compute hasse diagram                       */
berghofe@3599
   245
	/********************************************************************/
berghofe@3599
   246
berghofe@3599
   247
	public void hasseDiagram() {
berghofe@3599
   248
		Enumeration e1,e2;
berghofe@3599
   249
		Vertex vx1,vx2;
berghofe@3599
   250
berghofe@3599
   251
		/** construct adjacence matrix **/
berghofe@3599
   252
berghofe@3599
   253
		int vs=vertices.size();
berghofe@3599
   254
		boolean adj[][]=new boolean[vs][vs];
berghofe@3599
   255
		boolean adj2[][]=new boolean[vs][vs];
berghofe@3599
   256
		int i,j,k;
berghofe@3599
   257
berghofe@3599
   258
		e1=getVertices();
berghofe@3599
   259
		for (i=0;i<vs;i++) {
berghofe@3599
   260
			vx1=(Vertex)(e1.nextElement());
berghofe@3599
   261
			e2=vx1.getChildren();
berghofe@3599
   262
			while (e2.hasMoreElements()) {
berghofe@3599
   263
				vx2=(Vertex)(e2.nextElement());
berghofe@3599
   264
				j=vertices.indexOf(vx2);
berghofe@3599
   265
				adj[i][j]=true;
berghofe@3599
   266
				adj2[i][j]=true;
berghofe@3599
   267
			}
berghofe@3599
   268
		}
berghofe@3599
   269
berghofe@3599
   270
		/** compute transitive closure R+ **/
berghofe@3599
   271
berghofe@3599
   272
		for (k=0;k<vs;k++)
berghofe@3599
   273
			for (i=0;i<vs;i++)
berghofe@3599
   274
				if (adj[i][k])
berghofe@3599
   275
					for (j=0;j<vs;j++)
berghofe@3599
   276
						adj[i][j] = adj[i][j] || adj[k][j];
berghofe@3599
   277
berghofe@3599
   278
		/** compute R \ (R+)^2 **/
berghofe@3599
   279
berghofe@3599
   280
		for (i=0;i<vs;i++)
berghofe@3599
   281
			for (j=0;j<vs;j++)
berghofe@3599
   282
				if (adj2[i][j]) {
berghofe@3599
   283
					vx1=(Vertex)(vertices.elementAt(i));
berghofe@3599
   284
					vx2=(Vertex)(vertices.elementAt(j));
berghofe@3599
   285
					for (k=0;k<vs;k++)
berghofe@3599
   286
						if (adj[i][k] && adj[k][j]) {
berghofe@3599
   287
							vx1.removeChild(vx2);
berghofe@3599
   288
							break;
berghofe@3599
   289
						}
berghofe@3599
   290
				}
berghofe@3599
   291
	}
berghofe@3599
   292
				
berghofe@3599
   293
	/********************************************************************/
berghofe@3599
   294
	/*                      insert dummy vertices                       */
berghofe@3599
   295
	/********************************************************************/
berghofe@3599
   296
berghofe@3599
   297
	public Vector insert_dummies(Vector v) {
berghofe@3599
   298
		Vector layers2=new Vector(10,10);
berghofe@3599
   299
		int n_edges;
berghofe@3599
   300
berghofe@3599
   301
		do {
berghofe@3599
   302
			Enumeration e1=v.elements(),e2;
berghofe@3599
   303
			Vector next=new Vector(10,10);
berghofe@3599
   304
berghofe@3599
   305
			layers2.addElement(v);
berghofe@3599
   306
			n_edges=0;
berghofe@3599
   307
			while (e1.hasMoreElements()) {
berghofe@3599
   308
				Vertex v1=(Vertex)(e1.nextElement());
berghofe@3599
   309
				e2=v1.getChildren();
berghofe@3599
   310
				while (e2.hasMoreElements()) {
berghofe@3599
   311
					n_edges++;
berghofe@3599
   312
					Vertex v2=(Vertex)(e2.nextElement());
berghofe@3599
   313
					if (v2.getDegree()!=v1.getDegree()+1) {
berghofe@3599
   314
						Vertex v3=new DummyVertex();
berghofe@3599
   315
						v3.addChild(v2);
berghofe@3599
   316
						v3.setDegree(v1.getDegree()+1);
berghofe@3599
   317
						v1.removeChild(v2);
berghofe@3599
   318
						v1.addChild(v3);
berghofe@3599
   319
						next.addElement(v3);
berghofe@3599
   320
						addVertex(v3);
berghofe@3599
   321
					} else if (next.indexOf(v2)<0) next.addElement(v2);
berghofe@3599
   322
				}
berghofe@3599
   323
			}
berghofe@3599
   324
			v=next;
berghofe@3599
   325
			numEdges.addElement(new Integer(n_edges));
berghofe@3599
   326
		} while (!v.isEmpty());
berghofe@3599
   327
		return layers2;
berghofe@3599
   328
	}
berghofe@3599
   329
berghofe@3599
   330
	/********************************************************************/
berghofe@3599
   331
	/*                     calculation of crossings                     */
berghofe@3599
   332
	/********************************************************************/
berghofe@3599
   333
berghofe@3599
   334
	public int count_crossings(Vector layers,int oldcr) {
berghofe@3599
   335
		int i,j,y1,y2,cr=0,l;
berghofe@3599
   336
		for (l=0;l<layers.size()-1;l++) {
berghofe@3599
   337
			Vector v1=(Vector)(layers.elementAt(l));
berghofe@3599
   338
			for (i=0;i<v1.size();i++) {
berghofe@3599
   339
				Enumeration e2=((Vertex)(v1.elementAt(i))).getChildren();
berghofe@3599
   340
				while (e2.hasMoreElements()) {
berghofe@3599
   341
					y1=((Vector)(layers.elementAt(l+1))).indexOf(e2.nextElement());
berghofe@3599
   342
					for (j=0;j<i;j++) {
berghofe@3599
   343
						Enumeration e3=((Vertex)(v1.elementAt(j))).getChildren();
berghofe@3599
   344
						while (e3.hasMoreElements()) {
berghofe@3599
   345
							y2=((Vector)(layers.elementAt(l+1))).indexOf(e3.nextElement());
berghofe@3599
   346
							if (y1<y2) {
berghofe@3599
   347
								cr++;
berghofe@3599
   348
								if (cr>=oldcr) return cr;
berghofe@3599
   349
							}
berghofe@3599
   350
						}
berghofe@3599
   351
					}
berghofe@3599
   352
				}
berghofe@3599
   353
			}
berghofe@3599
   354
		}
berghofe@3599
   355
		return cr;
berghofe@3599
   356
	}
berghofe@3599
   357
berghofe@3599
   358
	/********************************************************************/
berghofe@3599
   359
	/* calculation of crossings where vertices vx1 and vx2 are involved */
berghofe@3599
   360
	/* vx1 and vx2 must be in same layer and vx1 is left from vx2       */
berghofe@3599
   361
	/********************************************************************/
berghofe@3599
   362
berghofe@3599
   363
	public int count_crossings_2(Vector layers,Vertex vx1,Vertex vx2,int oldcr) {
berghofe@3599
   364
		int i,cr=0,l=vx1.getDegree();
berghofe@3599
   365
		Vertex va,vb;
berghofe@3599
   366
		Vector layer;
berghofe@3599
   367
		Enumeration e1,e2;
berghofe@3599
   368
berghofe@3599
   369
		if (l>0) {
berghofe@3599
   370
			layer=(Vector)(layers.elementAt(l-1));
berghofe@3599
   371
			e1=vx1.getParents();
berghofe@3599
   372
			while (e1.hasMoreElements()) {
berghofe@3599
   373
				va=(Vertex)(e1.nextElement());
berghofe@3599
   374
				i=layer.indexOf(va);
berghofe@3599
   375
				e2=vx2.getParents();
berghofe@3599
   376
				while (e2.hasMoreElements()) {
berghofe@3599
   377
					vb=(Vertex)(e2.nextElement());
berghofe@3599
   378
					if (layer.indexOf(vb)<i) {
berghofe@3599
   379
						cr++;
berghofe@3599
   380
						if (cr>=oldcr) return cr;
berghofe@3599
   381
					}
berghofe@3599
   382
				}
berghofe@3599
   383
			}
berghofe@3599
   384
		}
berghofe@3599
   385
		if (l<layers.size()-1) {
berghofe@3599
   386
			layer=(Vector)(layers.elementAt(l+1));
berghofe@3599
   387
			e1=vx1.getChildren();
berghofe@3599
   388
			while (e1.hasMoreElements()) {
berghofe@3599
   389
				va=(Vertex)(e1.nextElement());
berghofe@3599
   390
				i=layer.indexOf(va);
berghofe@3599
   391
				e2=vx2.getChildren();
berghofe@3599
   392
				while (e2.hasMoreElements()) {
berghofe@3599
   393
					vb=(Vertex)(e2.nextElement());
berghofe@3599
   394
					if (layer.indexOf(vb)<i) {
berghofe@3599
   395
						cr++;
berghofe@3599
   396
						if (cr>=oldcr) return cr;
berghofe@3599
   397
					}
berghofe@3599
   398
				}
berghofe@3599
   399
			}
berghofe@3599
   400
		}
berghofe@3599
   401
		return cr;
berghofe@3599
   402
	}
berghofe@3599
   403
berghofe@3599
   404
	/********************************************************************/
berghofe@3599
   405
	/*       reduction of crossings by exchanging adjacent vertices     */
berghofe@3599
   406
	/********************************************************************/
berghofe@3599
   407
berghofe@3599
   408
	public void exchangeVertices(Vector layers,int oldcr) {
berghofe@3599
   409
		int i,l,c1,c2;
berghofe@3599
   410
		Vertex vx1,vx2;
berghofe@3599
   411
		Vector v1;
berghofe@3599
   412
berghofe@3599
   413
		for (l=0;l<layers.size();l++) {
berghofe@3599
   414
			v1=(Vector)(layers.elementAt(l));
berghofe@3599
   415
			for (i=0;i<v1.size()-1;i++) {
berghofe@3599
   416
				vx1=(Vertex)(v1.elementAt(i));
berghofe@3599
   417
				vx2=(Vertex)(v1.elementAt(i+1));
berghofe@3599
   418
				c1=count_crossings_2(layers,vx1,vx2,oldcr);
berghofe@3599
   419
				c2=count_crossings_2(layers,vx2,vx1,c1);
berghofe@3599
   420
				if (c2<c1) {
berghofe@3599
   421
					v1.setElementAt(vx2,i);
berghofe@3599
   422
					v1.setElementAt(vx1,i+1);
berghofe@3599
   423
				}
berghofe@3599
   424
			}
berghofe@3599
   425
		}
berghofe@3599
   426
	}
berghofe@3599
   427
berghofe@3599
   428
	/********************************************************************/
berghofe@3599
   429
	/*                    minimization of crossings                     */
berghofe@3599
   430
	/********************************************************************/
berghofe@3599
   431
berghofe@3599
   432
	public Vector min_crossings(Vector layers) {
berghofe@3599
   433
		int n,i,l,k,z=0,cr2,cr=count_crossings(layers,Integer.MAX_VALUE);
berghofe@3599
   434
		boolean topdown=true,first=true;
berghofe@3599
   435
		Enumeration e1,e2;
berghofe@3599
   436
		Vector v1,v2,layers2=null,best=layers;
berghofe@3599
   437
		Vertex vx1,vx2;
berghofe@3599
   438
		n=0;
berghofe@3599
   439
		while (n<3 && cr>0) {
berghofe@3599
   440
			if (topdown) {
berghofe@3599
   441
				/** top-down-traversal **/
berghofe@3599
   442
berghofe@3599
   443
				layers2=new Vector(10,10);
berghofe@3599
   444
				for (l=0;l<layers.size();l++) {
berghofe@3599
   445
					v1=(Vector)(layers.elementAt(l));
berghofe@3599
   446
					if (l==0) layers2.addElement(v1.clone());
berghofe@3599
   447
					else {
berghofe@3599
   448
						v2=new Vector(10,10);
berghofe@3599
   449
						layers2.addElement(v2);
berghofe@3599
   450
						e1=v1.elements();
berghofe@3599
   451
						while (e1.hasMoreElements()) {
berghofe@3599
   452
							vx1=(Vertex)(e1.nextElement());
berghofe@3599
   453
							k=0;z=0;
berghofe@3599
   454
							e2=vx1.getParents();
berghofe@3599
   455
							while (e2.hasMoreElements()) {
berghofe@3599
   456
								k+=((Vector)(layers2.elementAt(l-1))).indexOf(e2.nextElement());
berghofe@3599
   457
								z++;
berghofe@3599
   458
							}
berghofe@3599
   459
							if (z>0)
berghofe@3599
   460
								vx1.setWeight(((double)(k))/z);
berghofe@3599
   461
							else if (first)
berghofe@3599
   462
								vx1.setWeight(Double.MAX_VALUE);
berghofe@3599
   463
							for (i=0;i<v2.size();i++)
berghofe@3599
   464
								if (vx1.getWeight()<((Vertex)(v2.elementAt(i))).getWeight()) break;
berghofe@3599
   465
							if (i==v2.size()) v2.addElement(vx1);
berghofe@3599
   466
							else v2.insertElementAt(vx1,i);
berghofe@3599
   467
						}
berghofe@3599
   468
					}
berghofe@3599
   469
				}
berghofe@3599
   470
			} else {
berghofe@3599
   471
				/** bottom-up-traversal **/
berghofe@3599
   472
berghofe@3599
   473
				layers2=new Vector(10,10);
berghofe@3599
   474
				for (l=layers.size()-1;l>=0;l--) {
berghofe@3599
   475
					v1=(Vector)(layers.elementAt(l));
berghofe@3599
   476
					if (l==layers.size()-1) layers2.addElement(v1.clone());
berghofe@3599
   477
					else {
berghofe@3599
   478
						v2=new Vector(10,10);
berghofe@3599
   479
						layers2.insertElementAt(v2,0);
berghofe@3599
   480
						e1=v1.elements();
berghofe@3599
   481
						while (e1.hasMoreElements()) {
berghofe@3599
   482
							vx1=(Vertex)(e1.nextElement());
berghofe@3599
   483
							k=0;z=0;
berghofe@3599
   484
							e2=vx1.getChildren();
berghofe@3599
   485
							while (e2.hasMoreElements()) {
berghofe@3599
   486
								k+=((Vector)(layers2.elementAt(1))).indexOf(e2.nextElement());
berghofe@3599
   487
								z++;
berghofe@3599
   488
							}
berghofe@3599
   489
							if (z>0)
berghofe@3599
   490
								vx1.setWeight(((double)(k))/z);
berghofe@3599
   491
							else if (first)
berghofe@3599
   492
								vx1.setWeight(Double.MAX_VALUE);
berghofe@3599
   493
							for (i=0;i<v2.size();i++)
berghofe@3599
   494
								if (vx1.getWeight()<((Vertex)(v2.elementAt(i))).getWeight()) break;
berghofe@3599
   495
							if (i==v2.size()) v2.addElement(vx1);
berghofe@3599
   496
							else v2.insertElementAt(vx1,i);
berghofe@3599
   497
						}
berghofe@3599
   498
					}
berghofe@3599
   499
				}
berghofe@3599
   500
			}
berghofe@3599
   501
			//exchangeVertices(layers2,cr);
berghofe@3599
   502
			topdown=!topdown;
berghofe@3599
   503
			first=false;
berghofe@3599
   504
			layers=layers2;
berghofe@3599
   505
berghofe@3599
   506
			cr2=count_crossings(layers2,cr);
berghofe@3599
   507
			if (cr2<cr) {
berghofe@3599
   508
				best=layers2;
berghofe@3599
   509
				cr=cr2;					
berghofe@3599
   510
			} else n++;
berghofe@3599
   511
		}
berghofe@3599
   512
berghofe@3599
   513
		while (true) {
berghofe@3599
   514
			exchangeVertices(best,cr);
berghofe@3599
   515
			cr2=count_crossings(best,cr);
berghofe@3599
   516
			if (cr2<cr)
berghofe@3599
   517
				cr=cr2;
berghofe@3599
   518
			else
berghofe@3599
   519
				break;
berghofe@3599
   520
		}
berghofe@3599
   521
berghofe@3599
   522
		return best;
berghofe@3599
   523
	}
berghofe@3599
   524
berghofe@3599
   525
	/********************************************************************/
berghofe@3599
   526
	/*                   set initial coordinates                        */
berghofe@3599
   527
	/********************************************************************/
berghofe@3599
   528
berghofe@3599
   529
	public void init_coordinates(Vector layers) {
berghofe@3599
   530
		int y=0;
berghofe@3599
   531
		Enumeration e1=layers.elements();
berghofe@3599
   532
		Enumeration e3=numEdges.elements();
berghofe@3599
   533
		while (e1.hasMoreElements()) {
berghofe@3599
   534
			Vector v1=(Vector)(e1.nextElement());
berghofe@3599
   535
			Enumeration e2=v1.elements();
berghofe@37737
   536
			int x=0;
berghofe@3599
   537
			while (e2.hasMoreElements()) {
berghofe@3599
   538
				Vertex ve=(Vertex)(e2.nextElement());
berghofe@37737
   539
				ve.setX(x+ve.box_width2());
berghofe@3599
   540
				ve.setY(y);
berghofe@37737
   541
				x+=ve.box_width()+20;
berghofe@3599
   542
			}
berghofe@3599
   543
			y+=box_height+Math.max(35,7*(((Integer)(e3.nextElement())).intValue()));
berghofe@3599
   544
		}
berghofe@3599
   545
	}
berghofe@3599
   546
berghofe@3599
   547
	/********************************************************************/
berghofe@3599
   548
	/*                       pendulum method                            */
berghofe@3599
   549
	/********************************************************************/
berghofe@3599
   550
berghofe@3599
   551
	public void pendulum(Vector layers) {
berghofe@3599
   552
		Vector layers2=new Vector(10,10);
berghofe@3599
   553
		Enumeration e1=layers.elements(),e2;
berghofe@3599
   554
		int i,j,d1,d2,k,offset,dsum;
berghofe@3599
   555
		Region r1,r2;
berghofe@3599
   556
		boolean change;
berghofe@3599
   557
berghofe@3599
   558
		while (e1.hasMoreElements()) {
berghofe@3599
   559
			e2=((Vector)(e1.nextElement())).elements();
berghofe@3599
   560
			Vector layer=new Vector(10,10);
berghofe@3599
   561
			layers2.addElement(layer);
berghofe@3599
   562
			while (e2.hasMoreElements()) {
berghofe@3599
   563
				Region r=new Region(this);
berghofe@3599
   564
				r.addVertex((Vertex)(e2.nextElement()));
berghofe@3599
   565
				layer.addElement(r);
berghofe@3599
   566
			}
berghofe@3599
   567
		}
berghofe@3599
   568
		for (k=0;k<10;k++) {
berghofe@3599
   569
			dsum=0;
berghofe@3599
   570
			for (j=1;j<layers2.size();j++) {
berghofe@3599
   571
				Vector l=(Vector)(layers2.elementAt(j));
berghofe@3599
   572
				if (l.size()>=2) {
berghofe@3599
   573
					do {
berghofe@3599
   574
						change=false;
berghofe@3599
   575
						d1=((Region)(l.firstElement())).pred_deflection();
berghofe@3599
   576
						for (i=0;i<l.size()-1;i++) {
berghofe@3599
   577
							r1=(Region)(l.elementAt(i));
berghofe@3599
   578
							r2=(Region)(l.elementAt(i+1));
berghofe@3599
   579
							d2=r2.pred_deflection();
berghofe@3599
   580
							if (r1.touching(r2) && (d1 <= 0 && d2 < d1 ||
berghofe@3599
   581
								d2 > 0 && d1 > d2 || d1 > 0 && d2 < 0)) {
berghofe@3599
   582
								r1.combine(r2);
berghofe@3599
   583
								l.removeElement(r2);
berghofe@3599
   584
								change=true;
berghofe@3599
   585
								d2=r1.pred_deflection();
berghofe@3599
   586
							}
berghofe@3599
   587
							d1=d2;
berghofe@3599
   588
						}
berghofe@3599
   589
					} while (change);
berghofe@3599
   590
				}
berghofe@3599
   591
				for (i=0;i<l.size();i++) {
berghofe@3599
   592
					r1=(Region)(l.elementAt(i));
berghofe@3599
   593
					d1=r1.pred_deflection();
berghofe@3599
   594
					offset=d1;
berghofe@3599
   595
					if (d1<0 && i>0) offset=-Math.min(
berghofe@3599
   596
						((Region)(l.elementAt(i-1))).spaceBetween(r1),-d1);
berghofe@3599
   597
					if (d1>=0 && i<l.size()-1) offset=Math.min(
berghofe@3599
   598
						r1.spaceBetween((Region)(l.elementAt(i+1))),d1);
berghofe@3599
   599
					r1.move(offset);
berghofe@3599
   600
					dsum+=Math.abs(d1);
berghofe@3599
   601
				}		
berghofe@3599
   602
			}
berghofe@3599
   603
			if (dsum==0) break;
berghofe@3599
   604
		}
berghofe@3599
   605
	}		
berghofe@3599
   606
berghofe@3599
   607
	/********************************************************************/
berghofe@3599
   608
	/*                      rubberband method                           */
berghofe@3599
   609
	/********************************************************************/
berghofe@3599
   610
berghofe@3599
   611
	public void rubberband(Vector layers) {
berghofe@3599
   612
		Enumeration e1,e2;
berghofe@3599
   613
		int i,n,k,d,d2;
berghofe@3599
   614
		Vector v;
berghofe@3599
   615
		Vertex vx;
berghofe@3599
   616
berghofe@3599
   617
		for (k=0;k<10;k++) {
berghofe@3599
   618
			e1=layers.elements();
berghofe@3599
   619
			while (e1.hasMoreElements()) {
berghofe@3599
   620
				v=(Vector)(e1.nextElement());
berghofe@3599
   621
				for (i=0;i<v.size();i++) {
berghofe@3599
   622
					n=0;d=0;
berghofe@3599
   623
					vx=(Vertex)(v.elementAt(i));
berghofe@3599
   624
					e2=vx.getChildren();
berghofe@3599
   625
					while (e2.hasMoreElements()) {
berghofe@3599
   626
						d+=((Vertex)(e2.nextElement())).getX()-vx.getX();
berghofe@3599
   627
						n++;
berghofe@3599
   628
					}
berghofe@3599
   629
					e2=vx.getParents();
berghofe@3599
   630
					while (e2.hasMoreElements()) {
berghofe@3599
   631
						d+=((Vertex)(e2.nextElement())).getX()-vx.getX();
berghofe@3599
   632
						n++;
berghofe@3599
   633
					}
berghofe@3599
   634
					d2=(n!=0?d/n:0);
berghofe@3599
   635
berghofe@37737
   636
					if (d<0 && (i==0 || ((Vertex)(v.elementAt(i-1))).rightX()+20 < vx.leftX()+d2) ||
berghofe@37737
   637
						d>0 && (i==v.size()-1 || ((Vertex)(v.elementAt(i+1))).leftX()-20 > vx.rightX()+d2))
berghofe@3599
   638
						vx.setX(vx.getX()+d2);
berghofe@3599
   639
				}
berghofe@3599
   640
			}
berghofe@3599
   641
		}
berghofe@3599
   642
	}
berghofe@3599
   643
berghofe@3599
   644
	/**** Intersection point of two lines (auxiliary function for calcSplines)   ****/
berghofe@3599
   645
	/**** Calculate intersection point of line which is parallel to line (p1,p2) ****/
berghofe@3599
   646
	/**** and leads through p5, with line (p3,p4)                                ****/
berghofe@3599
   647
berghofe@3599
   648
	Point intersect(Point p1,Point p2,Point p3,Point p4,Point p5) {
berghofe@3599
   649
		float x=0,y=0,s1=0,s2=0;
berghofe@3599
   650
berghofe@3599
   651
		if (p1.x!=p2.x)
berghofe@3599
   652
			s1=((float)(p2.y-p1.y))/(p2.x-p1.x);
berghofe@3599
   653
		if (p3.x!=p4.x)
berghofe@3599
   654
			s2=((float)(p4.y-p3.y))/(p4.x-p3.x);
berghofe@3599
   655
		if (p1.x==p2.x) {
berghofe@3599
   656
			x=p5.x;
berghofe@3599
   657
			y=s2*(p5.x-p3.x)+p3.y;
berghofe@3599
   658
		} else if (p3.x==p4.x) {
berghofe@3599
   659
			x=p3.x;
berghofe@3599
   660
			y=s1*(p3.x-p5.x)+p5.y;
berghofe@3599
   661
		} else {
berghofe@3599
   662
			x=(p5.x*s1-p3.x*s2+p3.y-p5.y)/(s1-s2);
berghofe@3599
   663
			y=s2*(x-p3.x)+p3.y;
berghofe@3599
   664
		}
berghofe@3599
   665
		return new Point(Math.round(x),Math.round(y));
berghofe@3599
   666
	}
berghofe@3599
   667
berghofe@3599
   668
	/**** Calculate control points (auxiliary function for calcSplines) ****/
berghofe@3599
   669
berghofe@3599
   670
	Points calcPoint(Point p1,Point p2,Point p3,int lboxx,int rboxx,int boxy) {
berghofe@3599
   671
berghofe@3599
   672
		/*** Points p1 , p2 , p3 define a triangle which encloses the spline.  ***/
berghofe@3599
   673
		/*** Check if adjacent boxes (specified by lboxx,rboxx and boxy)       ***/
berghofe@3599
   674
		/*** collide with the spline. In this case p1 and p3 are shifted by an ***/
berghofe@3599
   675
		/*** appropriate offset before they are returned                       ***/
berghofe@3599
   676
berghofe@3599
   677
		int xh1,xh2,bx=0,by=0;
berghofe@3599
   678
		boolean pt1 = boxy >= p1.y && boxy <= p3.y || boxy >= p3.y && boxy <= p1.y;
berghofe@3599
   679
		boolean pt2 = boxy+box_height >= p1.y && boxy+box_height <= p3.y ||
berghofe@3599
   680
                              boxy+box_height >= p3.y && boxy+box_height <= p1.y;
berghofe@3599
   681
		boolean move = false;
berghofe@3599
   682
		Point b;
berghofe@3599
   683
berghofe@3599
   684
		xh1 = p1.x+(boxy-p1.y)*(p3.x-p1.x)/(p3.y-p1.y);
berghofe@3599
   685
		xh2 = p1.x+(boxy+box_height-p1.y)*(p3.x-p1.x)/(p3.y-p1.y);
berghofe@3599
   686
berghofe@3599
   687
		if (xh1 <= lboxx && pt1 && xh2 <= lboxx && pt2) {
berghofe@3599
   688
			move = true;
berghofe@3599
   689
			bx = lboxx;
berghofe@3599
   690
			by = boxy + (xh1 < xh2 ? 0 : box_height ) ;
berghofe@3599
   691
		} else if (xh1 >= rboxx && pt1 && xh2 >= rboxx && pt2) {
berghofe@3599
   692
			move = true;
berghofe@3599
   693
			bx = rboxx;
berghofe@3599
   694
			by = boxy + (xh1 > xh2 ? 0 : box_height ) ;
berghofe@3599
   695
		} else if ( (xh1 <= lboxx || xh1 >= rboxx) && pt1) {
berghofe@3599
   696
			move = true;
berghofe@3599
   697
			bx = (xh1 <= lboxx ? lboxx : rboxx ) ;
berghofe@3599
   698
			by = boxy;
berghofe@3599
   699
		} else if ( (xh2 <= lboxx || xh2 >= rboxx) && pt2) {
berghofe@3599
   700
			move = true;
berghofe@3599
   701
			bx = (xh2 <= lboxx ? lboxx : rboxx ) ;
berghofe@3599
   702
			by = boxy+box_height;
berghofe@3599
   703
		}
berghofe@3599
   704
		b=new Point(bx,by);
berghofe@3599
   705
		if (move) return new Points(intersect(p1,p3,p1,p2,b),intersect(p1,p3,p2,p3,b));
berghofe@3599
   706
		else return new Points(p1,p3);
berghofe@3599
   707
	}
berghofe@3599
   708
berghofe@3599
   709
	/********************************************************************/
berghofe@3599
   710
	/*                        calculate splines                         */
berghofe@3599
   711
	/********************************************************************/
berghofe@3599
   712
berghofe@3599
   713
	public void calcSplines(Vector layers) {
berghofe@3599
   714
		Enumeration e2,e1=vertices.elements();
berghofe@3599
   715
		Vertex vx1,vx2,vx3;
berghofe@3599
   716
		Vector pos,layer;
berghofe@3599
   717
		int x1,y1,x2,y2,x3,y3,xh,k,leftx,rightx,spc;
berghofe@3599
   718
berghofe@3599
   719
		while (e1.hasMoreElements()) {
berghofe@3599
   720
			vx1=(Vertex)(e1.nextElement());
berghofe@3599
   721
			if (!vx1.isDummy()) {
berghofe@3599
   722
				e2=vx1.getChildren();
berghofe@3599
   723
				while (e2.hasMoreElements()) {
berghofe@3599
   724
					vx2=(Vertex)(e2.nextElement());
berghofe@3599
   725
					if (vx2.isDummy()) {
berghofe@3599
   726
						vx3=vx2;
berghofe@3599
   727
						/**** convert edge to spline ****/
berghofe@3599
   728
						pos=new Vector(10,10);
berghofe@3599
   729
						x1=vx1.getX();
berghofe@3599
   730
						y1=vx1.getY()+box_height;
berghofe@3599
   731
berghofe@3599
   732
						do {
berghofe@3599
   733
							/*** calculate position of control points ***/
berghofe@3599
   734
							x2=vx2.getX();
berghofe@3599
   735
							y2=vx2.getY();
berghofe@3599
   736
							layer=(Vector)(layers.elementAt(vx2.getDegree()));
berghofe@3599
   737
							k=layer.indexOf(vx2);
berghofe@3599
   738
							vx2=(Vertex)((vx2.getChildren()).nextElement());
berghofe@3599
   739
							x3=vx2.getX();
berghofe@3599
   740
							y3=vx2.getY();
berghofe@3599
   741
							spc=0;
berghofe@3599
   742
							leftx = k==0 /* || ((Vertex)(layer.elementAt(k-1))).isDummy() */ ?
berghofe@3599
   743
								Integer.MIN_VALUE:
berghofe@3599
   744
								((Vertex)(layer.elementAt(k-1))).rightX()+spc;
berghofe@3599
   745
							rightx = k==layer.size()-1 /* || ((Vertex)(layer.elementAt(k+1))).isDummy() */ ?
berghofe@3599
   746
								Integer.MAX_VALUE:
berghofe@3599
   747
								((Vertex)(layer.elementAt(k+1))).leftX()-spc;
berghofe@3599
   748
							xh=x2+box_height*(x3-x2)/(y3-y2);
berghofe@3599
   749
							if (!(x2<=x3 && xh>=rightx || x2>x3 && xh<=leftx)) {
berghofe@3599
   750
								/* top control point */
berghofe@3599
   751
								pos.addElement(new Integer(1));
berghofe@3599
   752
								y1=y2;
berghofe@3599
   753
							} else {
berghofe@3599
   754
								xh=x1+(y2-y1)*(x2-x1)/(y2+box_height-y1);
berghofe@3599
   755
								if (!(x2<=x1 && xh>=rightx || x2>x1 && xh<=leftx))
berghofe@3599
   756
									/* bottom control point */
berghofe@3599
   757
									pos.addElement(new Integer(2));
berghofe@3599
   758
								else
berghofe@3599
   759
									/* two control points needed */
berghofe@3599
   760
									pos.addElement(new Integer(3));
berghofe@3599
   761
								y1=y2+box_height;
berghofe@3599
   762
							}
berghofe@3599
   763
							x1=x2;
berghofe@3599
   764
						} while (vx2.isDummy());
berghofe@3599
   765
						pos.addElement(new Integer(1));
berghofe@3599
   766
berghofe@3599
   767
						/**** calculate triangles ****/
berghofe@3599
   768
						vx2=vx3;
berghofe@3599
   769
berghofe@3599
   770
						int pos1,pos2,i=0;
berghofe@3599
   771
						Vector pts=new Vector(10,10);
berghofe@3599
   772
						int lboxx,rboxx,boxy;
berghofe@3599
   773
berghofe@3599
   774
						x1=vx1.getX();
berghofe@3599
   775
						y1=vx1.getY()+box_height;
berghofe@3599
   776
						pts.addElement(new Point(x1,y1)); /** edge starting point **/
berghofe@3599
   777
						do {
berghofe@3599
   778
							x2=vx2.getX();
berghofe@3599
   779
							y2=vx2.getY();
berghofe@3599
   780
							pos1=((Integer)(pos.elementAt(i))).intValue();
berghofe@3599
   781
							pos2=((Integer)(pos.elementAt(i+1))).intValue();
berghofe@3599
   782
							i++;
berghofe@3599
   783
							layer=(Vector)(layers.elementAt(vx2.getDegree()));
berghofe@3599
   784
							k=layer.indexOf(vx2);
berghofe@3599
   785
							boxy=vx2.getY();
berghofe@3599
   786
							vx2=(Vertex)((vx2.getChildren()).nextElement());
berghofe@3599
   787
							x3=vx2.getX();
berghofe@3599
   788
							y3=vx2.getY();
berghofe@3599
   789
							if (pos1==2) y2+=box_height;
berghofe@3599
   790
							if (pos2==2) y3+=box_height;
berghofe@3599
   791
berghofe@3599
   792
							lboxx = (k==0 /* || ((Vertex)(layer.elementAt(k-1))).isDummy() */ ) ?
berghofe@3599
   793
								Integer.MIN_VALUE :
berghofe@3599
   794
								((Vertex)(layer.elementAt(k-1))).rightX();
berghofe@3599
   795
berghofe@3599
   796
							rboxx = (k==layer.size()-1 /* || ((Vertex)(layer.elementAt(k+1))).isDummy() */ ) ?
berghofe@3599
   797
								Integer.MAX_VALUE :
berghofe@3599
   798
								((Vertex)(layer.elementAt(k+1))).leftX();
berghofe@3599
   799
berghofe@3599
   800
							Point p1,p2,p3;
berghofe@3599
   801
							Points ps;
berghofe@3599
   802
berghofe@3599
   803
							p1 = new Point((x1+x2)/2,(y1+y2)/2);
berghofe@3599
   804
berghofe@3599
   805
							if (pos1<=2) {
berghofe@3599
   806
								/** one control point **/
berghofe@3599
   807
								p2 = new Point(x2,y2);
berghofe@3599
   808
								ps = calcPoint(p1,p2,new Point((x2+x3)/2,(y2+y3)/2),lboxx,rboxx,boxy);
berghofe@3599
   809
								pts.addElement(ps.p);
berghofe@3599
   810
								pts.addElement(p2);
berghofe@3599
   811
								pts.addElement(ps.q);
berghofe@3599
   812
							} else {
berghofe@3599
   813
								/** two control points **/
berghofe@3599
   814
								p2 = new Point(x2,y2-box_height);
berghofe@3599
   815
								p3 = new Point(x2,y2+box_height2);
berghofe@3599
   816
								ps = calcPoint(p1,p2,p3,lboxx,rboxx,boxy);
berghofe@3599
   817
								pts.addElement(ps.p);
berghofe@3599
   818
								pts.addElement(p2);
berghofe@3599
   819
								pts.addElement(ps.q);
berghofe@3599
   820
								p2 = new Point(x2,y2+box_height*2);
berghofe@3599
   821
								ps = calcPoint(p3,p2,new Point((p2.x+x3)/2,(p2.y+y3)/2),
berghofe@3599
   822
								               lboxx,rboxx,boxy);
berghofe@3599
   823
								pts.addElement(ps.p);
berghofe@3599
   824
								pts.addElement(p2);
berghofe@3599
   825
								pts.addElement(ps.q);
berghofe@3599
   826
							}
berghofe@3599
   827
							x1=p2.x;
berghofe@3599
   828
							y1=p2.y;
berghofe@3599
   829
						} while (vx2.isDummy());
berghofe@3599
   830
berghofe@3599
   831
						pts.addElement(new Point(vx2.getX(),vx2.getY())); /** edge end point **/
berghofe@3599
   832
						splines.addElement(new Spline(pts));
berghofe@3599
   833
					}
berghofe@3599
   834
				}
berghofe@3599
   835
			}
berghofe@3599
   836
		}
berghofe@3599
   837
	}
berghofe@3599
   838
berghofe@3599
   839
	/********************************************************************/
berghofe@3599
   840
	/*                      calculate bounding box                      */
berghofe@3599
   841
	/********************************************************************/
berghofe@3599
   842
berghofe@3599
   843
	public void calcBoundingBox() {
berghofe@3599
   844
		min_y=min_x=Integer.MAX_VALUE;
berghofe@3599
   845
		max_y=max_x=Integer.MIN_VALUE;
berghofe@3599
   846
berghofe@3599
   847
		Enumeration e1=vertices.elements();
berghofe@3599
   848
		Vertex v;
berghofe@3599
   849
berghofe@3599
   850
		while (e1.hasMoreElements()) {
berghofe@3599
   851
			v=(Vertex)(e1.nextElement());
berghofe@3599
   852
			min_x=Math.min(min_x,v.leftX());
berghofe@3599
   853
			max_x=Math.max(max_x,v.rightX());
berghofe@3599
   854
			min_y=Math.min(min_y,v.getY());
berghofe@3599
   855
			max_y=Math.max(max_y,v.getY()+box_height);
berghofe@3599
   856
		}
berghofe@3599
   857
		min_x-=20;
berghofe@3599
   858
		min_y-=20;
berghofe@3599
   859
		max_x+=20;
berghofe@3599
   860
		max_y+=20;
berghofe@3599
   861
	}
berghofe@3599
   862
berghofe@3599
   863
	/********************************************************************/
berghofe@3599
   864
	/*                           draw graph                             */
berghofe@3599
   865
	/********************************************************************/
berghofe@3599
   866
					 
berghofe@3599
   867
	public void draw(Graphics g) {
berghofe@3599
   868
		if (box_height==0) layout(g);
berghofe@3599
   869
berghofe@3599
   870
		g.translate(-min_x,-min_y);
berghofe@3599
   871
berghofe@3599
   872
		Enumeration e1=vertices.elements();
berghofe@3599
   873
		while (e1.hasMoreElements())
berghofe@3599
   874
			((Vertex)(e1.nextElement())).draw(g);
berghofe@3599
   875
berghofe@3599
   876
		e1=splines.elements();
berghofe@3599
   877
		while (e1.hasMoreElements())
berghofe@3599
   878
			((Spline)(e1.nextElement())).draw(g);
berghofe@3599
   879
	}
berghofe@3599
   880
berghofe@3599
   881
	/********************************************************************/
berghofe@3599
   882
	/*               return vertex at position (x,y)                    */
berghofe@3599
   883
	/********************************************************************/
berghofe@3599
   884
berghofe@3599
   885
	public Vertex vertexAt(int x,int y) {
berghofe@3599
   886
		Enumeration e1=vertices.elements();
berghofe@3599
   887
		while (e1.hasMoreElements()) {
berghofe@3599
   888
			Vertex v=(Vertex)(e1.nextElement());
berghofe@3599
   889
			if (v.contains(x,y)) return v;
berghofe@3599
   890
		}
berghofe@3599
   891
		return null;
berghofe@3599
   892
	}
berghofe@3599
   893
berghofe@3599
   894
	/********************************************************************/
berghofe@3599
   895
	/*       encode list of vertices (as array of vertice numbers)      */
berghofe@3599
   896
	/********************************************************************/
berghofe@3599
   897
berghofe@3599
   898
	public Vector encode(Vector v) {
berghofe@3599
   899
		Vector code=new Vector(10,10);
berghofe@3599
   900
		Enumeration e1=v.elements();
berghofe@3599
   901
berghofe@3599
   902
		while (e1.hasMoreElements()) {
berghofe@3599
   903
			Vertex vx=(Vertex)(e1.nextElement());
berghofe@3599
   904
			if (vx.getNumber()>=0)
berghofe@3599
   905
				code.addElement(new Integer(vx.getNumber()));
berghofe@3599
   906
		}
berghofe@3599
   907
		return code;
berghofe@3599
   908
	}
berghofe@3599
   909
berghofe@3599
   910
	/********************************************************************/
berghofe@3599
   911
	/*                      get vertex with number n                    */
berghofe@3599
   912
	/********************************************************************/
berghofe@3599
   913
berghofe@3599
   914
	public Vertex getVertexByNum(int x) {
berghofe@3599
   915
		Enumeration e1=vertices.elements();
berghofe@3599
   916
berghofe@3599
   917
		while (e1.hasMoreElements()) {
berghofe@3599
   918
			Vertex vx=(Vertex)(e1.nextElement());
berghofe@3599
   919
			if (vx.getNumber()==x) return vx;
berghofe@3599
   920
		}
berghofe@3599
   921
		return null;
berghofe@3599
   922
	}
berghofe@3599
   923
berghofe@3599
   924
	/********************************************************************/
berghofe@3599
   925
	/*                      decode list of vertices                     */
berghofe@3599
   926
	/********************************************************************/
berghofe@3599
   927
berghofe@3599
   928
	public Vector decode(Vector code) {
berghofe@3599
   929
		Enumeration e1=code.elements();
berghofe@3599
   930
		Vector vec=new Vector(10,10);
berghofe@3599
   931
berghofe@3599
   932
		while (e1.hasMoreElements()) {
berghofe@3599
   933
			int i=((Integer)(e1.nextElement())).intValue();
berghofe@3599
   934
			//Vertex vx=getVertexByNum(i);
berghofe@3599
   935
			//if (vx!=null) vec.addElement(vx);
berghofe@3599
   936
			vec.addElement(vertices2[i]);
berghofe@3599
   937
		}
berghofe@3599
   938
		return vec;
berghofe@3599
   939
	}
berghofe@3599
   940
berghofe@3599
   941
	/********************************************************************/
berghofe@3599
   942
	/*                       collapse vertices                          */
berghofe@3599
   943
	/********************************************************************/
berghofe@3599
   944
berghofe@3599
   945
	public void collapse(Vector vs,String name,Vector inflate) {
berghofe@3599
   946
		Enumeration e1,e2,e3;
berghofe@3599
   947
		boolean nonempty=false;
berghofe@3599
   948
		Vertex vx3,vx2,vx1;
berghofe@3599
   949
		
berghofe@3599
   950
		e1=vertices.elements();
berghofe@3599
   951
berghofe@3599
   952
		vx1=new NormalVertex(name);
berghofe@3599
   953
		vx1.setInflate(inflate);
berghofe@3599
   954
berghofe@3599
   955
		while (e1.hasMoreElements()) {
berghofe@3599
   956
			vx2=(Vertex)(e1.nextElement());
berghofe@3599
   957
berghofe@3599
   958
			if (vs.indexOf(vx2)<0) {
berghofe@3599
   959
				e2=vx2.getParents();
berghofe@3599
   960
				while (e2.hasMoreElements()) {
berghofe@3599
   961
					vx3=(Vertex)(e2.nextElement());
berghofe@3599
   962
					if (vs.indexOf(vx3)>=0) {
berghofe@3599
   963
						if (!vx1.isChild(vx2))
berghofe@3599
   964
							vx1.addChild(vx2);
berghofe@3599
   965
						vx3.removeChild(vx2);
berghofe@3599
   966
					}
berghofe@3599
   967
				}
berghofe@3599
   968
berghofe@3599
   969
				e2=vx2.getChildren();
berghofe@3599
   970
				while (e2.hasMoreElements()) {
berghofe@3599
   971
					vx3=(Vertex)(e2.nextElement());
berghofe@3599
   972
					if (vs.indexOf(vx3)>=0) {
berghofe@3599
   973
						if (!vx2.isChild(vx1))
berghofe@3599
   974
							vx2.addChild(vx1);
berghofe@3599
   975
						vx2.removeChild(vx3);
berghofe@3599
   976
					}
berghofe@3599
   977
				}
berghofe@3599
   978
			} else { nonempty=true; }
berghofe@3599
   979
		}
berghofe@3599
   980
berghofe@3599
   981
		e1=vs.elements();
berghofe@3599
   982
		while (e1.hasMoreElements())
berghofe@3599
   983
			try {
berghofe@3599
   984
				removeVertex((Vertex)(e1.nextElement()));
berghofe@3599
   985
			} catch (NoSuchElementException exn) {}
berghofe@3599
   986
berghofe@3599
   987
		if (nonempty) addVertex(vx1);
berghofe@3599
   988
	}
berghofe@3599
   989
berghofe@3599
   990
	/********************************************************************/
berghofe@3599
   991
	/*                      PostScript output                           */
berghofe@3599
   992
	/********************************************************************/
berghofe@3599
   993
berghofe@3599
   994
	public void PS(String fname,boolean printable) throws IOException {
berghofe@3599
   995
		FileOutputStream f = new FileOutputStream(fname);
berghofe@6541
   996
		PrintWriter p = new PrintWriter(f, true);
berghofe@3599
   997
berghofe@3599
   998
		if (printable)
berghofe@3599
   999
			p.println("%!PS-Adobe-2.0\n\n%%BeginProlog");
berghofe@3599
  1000
		else {
berghofe@3599
  1001
			p.println("%!PS-Adobe-2.0 EPSF-2.0\n%%Orientation: Portrait");
berghofe@3599
  1002
			p.println("%%BoundingBox: "+min_x+" "+min_y+" "+max_x+" "+max_y);
berghofe@3599
  1003
			p.println("%%EndComments\n\n%%BeginProlog");
berghofe@3599
  1004
		}
berghofe@3599
  1005
		p.println("/m { moveto } def /l { lineto } def /n { newpath } def");
berghofe@3599
  1006
		p.println("/s { stroke } def /c { curveto } def");
berghofe@3599
  1007
		p.println("/b { n 0 0 m dup true charpath pathbbox 1 index 4 index sub");
berghofe@3599
  1008
		p.println("7 index exch sub 2 div 9 index add 1 index 4 index sub 7 index exch sub");
berghofe@3599
  1009
		p.println("2 div 9 index add 2 index add m pop pop pop pop");
berghofe@3599
  1010
		p.println("1 -1 scale show 1 -1 scale n 3 index 3 index m 1 index 0 rlineto");
berghofe@3599
  1011
		p.println("0 exch rlineto neg 0 rlineto closepath s pop pop } def");
berghofe@3599
  1012
		p.println("%%EndProlog\n");
berghofe@3599
  1013
		if (printable) {
berghofe@3599
  1014
			int hsize=max_x-min_x;
berghofe@3599
  1015
			int vsize=max_y-min_y;
berghofe@3599
  1016
			if (hsize>vsize) {
berghofe@3599
  1017
				// Landscape output
berghofe@3599
  1018
				double scale=Math.min(1,Math.min(750.0/hsize,500.0/vsize));
berghofe@3599
  1019
				double trans_x=50+max_y*scale+(500-scale*vsize)/2.0;
berghofe@3599
  1020
				double trans_y=50+max_x*scale+(750-scale*hsize)/2.0;
berghofe@3599
  1021
				p.println(trans_x+" "+trans_y+" translate");
berghofe@3599
  1022
				p.println("-90 rotate");
berghofe@3599
  1023
				p.println(scale+" "+(-scale)+" scale");
berghofe@3599
  1024
			} else {
berghofe@3599
  1025
				// Portrait output
berghofe@3599
  1026
				double scale=Math.min(1,Math.min(500.0/hsize,750.0/vsize));
berghofe@3599
  1027
				double trans_x=50-min_x*scale+(500-scale*hsize)/2.0;
berghofe@3599
  1028
				double trans_y=50+max_y*scale+(750-scale*vsize)/2.0;
berghofe@3599
  1029
				p.println(trans_x+" "+trans_y+" translate");
berghofe@3599
  1030
				p.println(scale+" "+(-scale)+" scale");
berghofe@3599
  1031
			}
berghofe@3599
  1032
		} else
berghofe@3599
  1033
			p.println("0 "+(max_y+min_y)+" translate\n1 -1 scale");
berghofe@3599
  1034
berghofe@3599
  1035
		p.println("/Helvetica findfont 12 scalefont setfont");
berghofe@3599
  1036
		p.println("0.5 setlinewidth");
berghofe@3599
  1037
berghofe@3599
  1038
		Enumeration e1=vertices.elements();
berghofe@3599
  1039
		while (e1.hasMoreElements())
berghofe@3599
  1040
			((Vertex)(e1.nextElement())).PS(p);
berghofe@3599
  1041
berghofe@3599
  1042
		e1=splines.elements();
berghofe@3599
  1043
		while (e1.hasMoreElements())
berghofe@3599
  1044
			((Spline)(e1.nextElement())).PS(p);
berghofe@3599
  1045
berghofe@3599
  1046
		if (printable) p.println("showpage");
berghofe@3599
  1047
berghofe@3599
  1048
		f.close();
berghofe@3599
  1049
	}
berghofe@3599
  1050
}
berghofe@3599
  1051
berghofe@3599
  1052
/**** Return value of function calcPoint ****/
berghofe@3599
  1053
berghofe@3599
  1054
class Points {
berghofe@3599
  1055
	public Point p,q;
berghofe@3599
  1056
berghofe@3599
  1057
	public Points(Point p1,Point p2) {
berghofe@3599
  1058
		p=p1;q=p2;
berghofe@3599
  1059
	}
berghofe@3599
  1060
}
berghofe@3599
  1061