class1.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /*
  11. * Classify edges for rank assignment phase to
  12. * create temporary edges.
  13. */
  14. #include <dotgen/dot.h>
  15. #include <stdbool.h>
  16. bool nonconstraint_edge(edge_t *e) {
  17. char *constr;
  18. if (E_constr && (constr = agxget(e, E_constr))) {
  19. if (constr[0] && !mapbool(constr))
  20. return true;
  21. }
  22. return false;
  23. }
  24. static void
  25. interclust1(graph_t * g, node_t * t, node_t * h, edge_t * e)
  26. {
  27. node_t *v, *t0, *h0;
  28. int offset, t_len, h_len, t_rank, h_rank;
  29. edge_t *rt, *rh;
  30. if (ND_clust(agtail(e)))
  31. t_rank = ND_rank(agtail(e)) - ND_rank(GD_leader(ND_clust(agtail(e))));
  32. else
  33. t_rank = 0;
  34. if (ND_clust(aghead(e)))
  35. h_rank = ND_rank(aghead(e)) - ND_rank(GD_leader(ND_clust(aghead(e))));
  36. else
  37. h_rank = 0;
  38. offset = ED_minlen(e) + t_rank - h_rank;
  39. if (offset > 0) {
  40. t_len = 0;
  41. h_len = offset;
  42. } else {
  43. t_len = -offset;
  44. h_len = 0;
  45. }
  46. v = virtual_node(g);
  47. ND_node_type(v) = SLACKNODE;
  48. t0 = UF_find(t);
  49. h0 = UF_find(h);
  50. rt = make_aux_edge(v, t0, t_len, CL_BACK * ED_weight(e));
  51. rh = make_aux_edge(v, h0, h_len, ED_weight(e));
  52. ED_to_orig(rt) = ED_to_orig(rh) = e;
  53. }
  54. void class1(graph_t * g)
  55. {
  56. node_t *n, *t, *h;
  57. edge_t *e, *rep;
  58. mark_clusters(g);
  59. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  60. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  61. /* skip edges already processed */
  62. if (ED_to_virt(e))
  63. continue;
  64. /* skip edges that we want to ignore in this phase */
  65. if (nonconstraint_edge(e))
  66. continue;
  67. t = UF_find(agtail(e));
  68. h = UF_find(aghead(e));
  69. /* skip self, flat, and intra-cluster edges */
  70. if (t == h)
  71. continue;
  72. /* inter-cluster edges require special treatment */
  73. if (ND_clust(t) || ND_clust(h)) {
  74. interclust1(g, agtail(e), aghead(e), e);
  75. continue;
  76. }
  77. if ((rep = find_fast_edge(t, h)))
  78. merge_oneway(e, rep);
  79. else
  80. virtual_edge(t, h, e);
  81. }
  82. }
  83. }