1 21 22 package hero.client.grapheditor; 23 24 import com.jgraph.JGraph; 25 import com.jgraph.graph.*; 26 import java.awt.Rectangle ; 27 import java.awt.Point ; 28 import java.util.*; 29 30 34 35 public class Spring { 36 37 static java.util.ResourceBundle resource = java.util.ResourceBundle.getBundle("resources.Traduction"); 38 39 protected WFGraph graph; 40 41 42 private CellView[] vertices = null; 43 44 private static Rectangle rect; 45 private static double xmax,xmin,ymax,ymin; 46 private static int orderedList[]; private static int N; private static int EDGES; private static long D[][]; private static double K[][]; private static double Ko; private static double L[][]; private static double epsilon; 56 private static double delta[]; 57 private static int MAX_TIMES_REPOSITIONED = 10; private static int numTimesRepositioned = 0; private static int NUM_TIMES_MOVED[]; 65 private static int HY_SIZE = 10; private static int HY_PERCENTAGE = 5; private static double E,E_HY[]; private static int COUNTER = 0; 69 70 private static int mv = -1; private static double partial_x,partial_y,partial_xx, 72 partial_xy,partial_yx,partial_yy; 73 private static boolean connected; 74 75 private int DEBUG = 3; 76 77 public Spring() { 78 this(3); 79 } 80 81 public Spring(int debug) { 82 DEBUG = debug; 83 } 84 85 public String compute(WFGraph G) 86 { 87 this.graph = G; 88 double tempValue,maxValue,maxDel; int maxTimes = 0; 89 int mvi,i; 90 int v,u; 92 rect = G.fromScreen(G.getBounds()); 93 94 Initialize(G); 96 97 102 112 if (false) { 117 return resource.getString("spring.error"); 119 } 120 121 122 while(DEBUG-->0) 125 { 126 CheckPositions(G); 128 129 131 maxDel = 0; 132 for (int index = 0; index < N; index++) { 133 v = index; 135 delta[v]=Math.sqrt(findDelta2(G,v)); 136 if (delta[v] > maxDel) 137 maxDel = delta[v]; 138 if (NUM_TIMES_MOVED[v] > maxTimes) 139 maxTimes = NUM_TIMES_MOVED[v]; 140 } 142 143 mv = 0; mvi = 0; 144 maxValue = 0; 145 v = mv; 146 for (int index = 1; index < N; index++) 147 { 148 v = index; 149 if (maxTimes != 0) 150 tempValue = TempFunction 151 (delta[v]/maxDel, 152 1 - NUM_TIMES_MOVED[v]); 153 else 154 tempValue = delta[v]/maxDel; 156 if (tempValue > maxValue) 157 { 158 mv = v; mvi = mv; 159 maxValue = tempValue; 160 } 161 } 162 163 164 if (delta[mvi] < epsilon) 168 { 169 break; 171 } 172 if (COUNTER > HY_SIZE) 173 if (E_HY[COUNTER%HY_SIZE] * HY_PERCENTAGE/100.0 > (E = findE(G))) 174 { 175 break; 177 } 178 179 182 E_HY[COUNTER%HY_SIZE] = E; 183 184 numTimesRepositioned = 0; 185 186 while ( (delta[mvi] > epsilon) 187 && (numTimesRepositioned < MAX_TIMES_REPOSITIONED) ) 188 { 189 MoveToNewPosition2(G); delta[mvi] = Math.sqrt(findDelta2(G,mv)); 194 numTimesRepositioned++; 195 } 197 NUM_TIMES_MOVED[mvi]++; 198 199 201 203 207 } return null; 209 210 } 212 213 214 215 216 private void Initialize(JGraph G) 217 { 218 int i; 220 EDGES = 0; 221 Object [] cells = G.getRoots(); 223 LinkedList list = new LinkedList(); 224 for (int idx = 0; idx < cells.length; idx++) 225 if (graph.isVertex(cells[idx])) 226 list.add(cells[idx]); 227 else if (graph.isEdge(cells[idx])) 228 EDGES++; 229 230 vertices = graph.getView().getMapping(list.toArray()); 232 N = vertices.length; 234 makeOrderedList(G); 235 NUM_TIMES_MOVED = new int[N]; 236 for (i=0;i<N;i++) 237 NUM_TIMES_MOVED[i] = 0; 238 EDGES=0; 239 246 epsilon = 0.5*(N+EDGES); 248 findDistances(G); 249 find_l_and_k(G); 250 delta = new double[N]; 251 E_HY = new double[HY_SIZE]; 252 xmin = rect.x; xmax = xmin + rect.width; 253 ymin = rect.y; ymax = ymin + rect.height; 254 } 255 256 private void findDistances(JGraph G) 257 { 258 int s,u,v,p; 259 int i,j,vi,pi,si,ui; 260 boolean done[]; 261 Queue queue; 262 263 queue = new Queue(); 264 int vertexCount = vertices.length; done = new boolean[vertexCount]; 266 D = new long[vertexCount][vertexCount]; 267 268 269 270 for (i=0;i<vertexCount;i++) 271 for (j=i;j<vertexCount;j++) 272 { D[i][j] = 0; D[j][i] = 0; } 273 274 275 276 for (int index = 0; index < vertexCount; index++) { 277 278 279 for (i=0;i<vertexCount;i++) 280 done[i] = false; 281 282 done[index] = true; 283 284 CellView[] adj = getVerticesFor(G, index); 286 287 for (int idx2 = 0; idx2 < adj.length; idx2++) { 289 v = getIndexOf(adj[idx2]); 290 queue.push(v); 291 queue.push(index); 292 done[v] = true; 294 } 295 while (!(queue.isEmpty())) 296 { 297 v = queue.pop(); 298 p = queue.pop(); 299 D[index][v] = D[p][index] + 1; 301 D[v][index] = D[index][v]; 302 304 for (int idx3 = 0; idx3 < vertexCount; idx3++) { 305 306 CellView[] adj2 = getVerticesFor(G, idx3); 308 309 for (int idx2 = 0; idx2 < adj2.length; idx2++) { 310 u = getIndexOf(adj2[idx2]); 311 if (!(done[u])) 312 { 313 queue.push(u); 314 queue.push(v); 315 done[u] = true; 316 } 317 } 318 } 319 } 320 } 321 322 324 connected = true; 325 for (i=0;i<N;i++) 326 for (j=i+1;j<N;j++) 327 if (D[i][j]==0) 328 { 329 connected = false; 330 D[i][j] = Long.MAX_VALUE; 331 D[j][i] = Long.MAX_VALUE; 332 } 333 } 335 public int getIndexOf(CellView v) { 336 for (int i = 0; i < vertices.length; i++) 337 if (vertices[i] == v) 338 return i; 339 return 0; 341 } 342 343 public CellView[] getVerticesFor(JGraph G, int index) { 344 Set set = DefaultGraphModel.getEdges(G.getModel(), new Object []{vertices[index].getCell()}); 345 Object [] obj = set.toArray(); 346 if (obj != null) { 347 CellView[] adj = new CellView[obj.length]; 348 for (int i = 0; i < obj.length; i++) 349 adj[i] = (CellView) graph.getView().getMapping(graph.getNeighbour(obj[i], vertices[index]), false); 350 return adj; 351 } else 352 return new CellView[0]; 353 } 354 355 private void makeOrderedList(JGraph G) 356 { 357 int highestIndex,i; 358 CellView v; 359 360 orderedList = new int[vertices.length]; 361 for (int index = 0; index < vertices.length; index++) { 362 orderedList[index] = index; } 365 } 367 private static int enume(int Index) 368 { 369 int i; 370 371 for (i=0; ;i++) 372 if (orderedList[i] == Index) 373 return i; 374 } 376 private void find_l_and_k(JGraph G) 377 { 378 if(D.length == 0) 379 return; 380 381 int i,j; 382 long diam; 383 double Lo; 384 385 Ko = 0; 386 int vertexCount = vertices.length; 387 L = new double[vertexCount][vertexCount]; 388 K = new double[vertexCount][vertexCount]; 389 390 diam = D[0][0]; 391 for (i=0;i<vertexCount;i++) 392 for (j=i+1;j<vertexCount;j++) 393 { 394 if ((diam < D[i][j]) && (D[i][j] < Long.MAX_VALUE)) 395 diam = D[i][j]; 396 Ko+= D[i][j]; 397 } 398 Ko = Ko/vertexCount; 399 400 for (i=0;i<vertexCount;i++) 401 for (j=i+1;j<vertexCount;j++) 402 { 403 404 405 406 Lo = Math.sqrt(rect.width*rect.height/4)/diam; 407 L[i][j] = Lo*D[i][j]; 408 L[j][i] = L[i][j]; 409 if (D[i][j] < Long.MAX_VALUE) { 410 411 K[i][j] = Ko*Ko/(D[i][j]*D[i][j]); 412 } else { 414 K[i][j] = 0; 415 } 417 K[j][i] = K[i][j]; 418 } 419 } 421 422 423 424 425 private double findDelta2(JGraph G,int v) 426 { 427 findPartials(G,v); 428 double delta = (partial_x*partial_x+partial_y*partial_y); 429 return delta; 431 } 432 433 434 435 436 437 private void findPartials(JGraph G,int v) 438 { 439 int u; 440 int vi,ui; 441 double dx,dy,dd; 442 443 444 vi = v; 445 partial_x=0; 446 partial_y=0; 447 partial_xx=0; 448 partial_xy=0; 449 partial_yx=0; 450 partial_yy=0; 451 for (u = 0; u<N; u++) 452 if (v!=u) 453 { 454 ui = u; 455 dx = vertices[v].getBounds().x - vertices[u].getBounds().x; 456 dy = vertices[v].getBounds().y - vertices[u].getBounds().y; 457 dd = Math.sqrt(dx*dx+dy*dy); 458 partial_x+= K[vi][ui]*(dx-L[vi][ui]*dx/dd); 459 partial_y+= K[vi][ui]*(dy-L[vi][ui]*dy/dd); 460 partial_xx+= K[vi][ui]*(1-L[vi][ui]*dy*dy/(dd*dd*dd)); 461 partial_xy+= K[vi][ui]*(L[vi][ui]*dx*dy/(dd*dd*dd)); 462 partial_yx+= K[vi][ui]*(L[vi][ui]*dy*dx/(dd*dd*dd)); 463 partial_yy+= K[vi][ui]*(1-L[vi][ui]*dx*dx/(dd*dd*dd)); 464 } 466 } 467 468 private static double TempFunction(double del, double times) 469 { 470 return (0.5 * del + 0.5 * times); 471 } 472 473 474 475 476 477 private double findE(JGraph G) 478 { 479 int u,v; 480 int vi,ui; 481 double dx,dy,dd,dif; 482 double total=0; 483 484 for (v = 0; v <N; v++) 485 { 486 vi = v; 487 for (u = v; u<N; u++) 488 { 489 ui = u; 490 dx = vertices[v].getBounds().x - vertices[u].getBounds().x; 491 dy = vertices[v].getBounds().y - vertices[u].getBounds().y; 492 dd = Math.sqrt(dx*dx+dy*dy); 493 dif = dd - L[vi][ui]; 494 total+= K[vi][ui]*dif*dif; 495 } 496 } 497 return total/2; 498 } 499 500 501 502 503 504 505 private void MoveToNewPosition(JGraph G) 506 { 507 double A,B,C,D,E,F,dx,dy; 508 double xpos,ypos,xfrac,yfrac; 509 510 xpos = vertices[mv].getBounds().x; 511 ypos = vertices[mv].getBounds().y; 512 513 int mvi = mv; 514 findPartials(G,mv); 515 A = partial_xx; 516 B = partial_xy; 517 C = -(partial_x); 518 D = partial_yx; 519 E = partial_yy; 520 F = -(partial_y); 521 dy = (A*F-C*D)/(A*E-B*D); 522 dx = (C*E-B*F)/(A*E-B*D); 523 524 while ( (dy != 0) && (dx != 0) ) 525 { 526 if (xpos + dx < xmin) 527 xfrac = (xpos - xmin)/dx; 528 else if (xpos + dx > xmax) 529 xfrac = (xmax - xpos)/dx; 530 else 531 xfrac = 1; 532 533 534 if (ypos + dy < ymin) 535 yfrac = (ypos - ymin)/dy; 536 else if (ypos + dy > ymax) 537 yfrac = (ymax - ypos)/dy; 538 else 539 yfrac = 1; 540 543 if (xfrac < yfrac) 544 { 545 xpos += dx * xfrac; 546 dx *= (xfrac - 1); 547 ypos += dy * xfrac; 548 dy *= (1 - xfrac); 549 } 550 else if (yfrac < xfrac) 551 { 552 ypos += dy * yfrac; 553 dy *= (yfrac - 1); 554 xpos += dx * yfrac; 555 dx *= (1 - yfrac); 556 } 557 else 558 { 559 xpos += dx; 560 dx = 0; 561 ypos += dy; 562 dy = 0; 563 } 564 } 566 if (xpos < 0) xpos = 0; 567 if (ypos < 0) ypos = 0; 568 Point p = G.snap(new Point ((int) xpos, (int) ypos)); 569 vertices[mv].getBounds().setLocation(p); 570 vertices[mv].getBounds().setLocation(new Point ((int) xpos,(int) ypos)); 571 } 572 573 private void MoveToNewPosition1(JGraph G) 574 { 575 double A,B,C,D,E,F,dx,dy; 576 double xpos,ypos,xfrac,yfrac; 577 578 xpos = vertices[mv].getBounds().x; 579 ypos = vertices[mv].getBounds().y; 580 581 582 583 int mvi = mv; 584 findPartials(G,mv); 585 A = partial_xx; 586 B = partial_xy; 587 C = -(partial_x); 588 D = partial_yx; 589 E = partial_yy; 590 F = -(partial_y); 591 dy = (A*F-C*D)/(A*E-B*D); 592 dx = (C*E-B*F)/(A*E-B*D); 593 594 if (xpos + dx < xmin) 595 xfrac = (xpos - xmin)/dx; 596 else if (xpos + dx > xmax) 597 xfrac = (xmax - xpos)/dx; 598 else 599 xfrac = 1; 600 601 602 if (ypos + dy < ymin) 603 yfrac = (ypos - ymin)/dy; 604 else if (ypos + dy > ymax) 605 yfrac = (ymax - ypos)/dy; 606 else 607 yfrac = 1; 608 609 if (xfrac < yfrac) 610 { 611 yfrac = xfrac; 612 } 613 else if (yfrac < xfrac) 614 { 615 xfrac = yfrac; 616 } 617 double x = xpos+dx; 618 double y = ypos+dy; 619 620 xpos += dx*xfrac; 621 dx = 0; 622 ypos += dy*yfrac; 623 dy = 0; 624 625 if (xpos < 0) xpos = 0; 626 if (ypos < 0) ypos = 0; 627 Point p = G.snap(new Point ((int) xpos, (int) ypos)); 628 vertices[mv].getBounds().setLocation(p); 629 } 630 631 632 633 private void MoveToNewPosition2(JGraph G) 634 { 635 double A,B,C,D,E,F,dx,dy; 636 double xpos,ypos,xfrac,yfrac; 637 638 xpos = vertices[mv].getBounds().x; 639 ypos = vertices[mv].getBounds().y; 640 641 642 643 644 int mvi = mv; 645 findPartials(G,mv); 646 A = partial_xx; 647 B = partial_xy; 648 C = -(partial_x); 649 D = partial_yx; 650 E = partial_yy; 651 F = -(partial_y); 652 dy = (A*F-C*D)/(A*E-B*D); 653 dx = (C*E-B*F)/(A*E-B*D); 654 655 if (xpos < 0) xpos = 0; 656 if (ypos < 0) ypos = 0; 657 658 Point p = G.snap(new Point ((int) (xpos+dx), (int) (ypos+dy))); 659 vertices[mv].getBounds().setLocation(p); 660 } 661 662 663 664 private void CheckPositions(JGraph G) 665 { 666 int v,u; 667 int vi,ui; 668 double rand; 669 boolean OK = false; 670 671 OK = true; 674 for (v = 0; v < N; v++) 675 for (u = v; u<N; u++) 676 if ((vertices[v].getBounds().x == vertices[u].getBounds().x) 677 && (vertices[v].getBounds().y == vertices[u].getBounds().y)) 678 { 679 vi = v; 680 ui = u; 681 rand = (1.4*Math.random() - 1) * L[vi][ui]; 682 Point tmp = new Point (vertices[u].getBounds().x + (int) rand , vertices[u].getBounds().y); 683 vertices[u].getBounds().setLocation(tmp); 684 rand = (1.4*Math.random() - 1) * L[vi][ui]; 685 tmp = new Point (vertices[u].getBounds().x + (int) rand , vertices[u].getBounds().y); 686 vertices[u].getBounds().setLocation(tmp); 687 OK = false; 688 } 689 } 691 692 693 } | Popular Tags |