| author | wenzelm | 
| Sun, 04 Jan 2015 21:01:27 +0100 | |
| changeset 59262 | 5cd92c743958 | 
| parent 59261 | 5e7280814916 | 
| child 59263 | 03aedb32a763 | 
| permissions | -rw-r--r-- | 
| 59232 | 1  | 
/* Title: Tools/Graphview/layout.scala  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
2  | 
Author: Markus Kaiser, TU Muenchen  | 
| 59240 | 3  | 
Author: Makarius  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
4  | 
|
| 59261 | 5  | 
DAG layout algorithm, according to:  | 
6  | 
||
7  | 
Georg Sander, "Graph Layout through the VCG Tool", in: Graph Drawing,  | 
|
8  | 
DIMACS International Workshop (GD'94), Springer LNCS 894, 1995.  | 
|
9  | 
||
10  | 
http://dx.doi.org/10.1007/3-540-58950-3_371  | 
|
11  | 
ftp://ftp.cs.uni-sb.de/pub/graphics/vcg/doc/tr-A03-94.ps.gz  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
12  | 
*/  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
13  | 
|
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
14  | 
package isabelle.graphview  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
15  | 
|
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
16  | 
|
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
17  | 
import isabelle._  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
18  | 
|
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
19  | 
|
| 59232 | 20  | 
object Layout  | 
| 49744 | 21  | 
{
 | 
| 59262 | 22  | 
  object Point { val zero: Point = Point(0.0, 0.0) }
 | 
23  | 
case class Point(x: Double, y: Double)  | 
|
| 50469 | 24  | 
|
| 59262 | 25  | 
private type Key = Graph_Display.Node  | 
26  | 
private type Coordinates = Map[Key, Point]  | 
|
27  | 
private type Level = List[Key]  | 
|
28  | 
private type Levels = List[Level]  | 
|
29  | 
||
30  | 
val empty = new Layout(Map.empty, Map.empty)  | 
|
| 50470 | 31  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
32  | 
val pendulum_iterations = 10  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
33  | 
val minimize_crossings_iterations = 40  | 
| 50469 | 34  | 
|
| 59260 | 35  | 
def make(metrics: Visualizer.Metrics, graph: Graph_Display.Graph): Layout =  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
36  | 
  {
 | 
| 59232 | 37  | 
if (graph.is_empty) empty  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
38  | 
    else {
 | 
| 59260 | 39  | 
def box_width(key: Key): Double =  | 
40  | 
(metrics.string_bounds(key.toString).getWidth + metrics.pad).ceil  | 
|
41  | 
||
42  | 
val box_distance = (graph.keys_iterator.map(box_width(_)).max + metrics.gap).ceil  | 
|
43  | 
||
44  | 
def box_height(level: Level): Double =  | 
|
45  | 
(metrics.char_width * 1.5 * (5 max level.length)).ceil  | 
|
46  | 
||
47  | 
||
| 49744 | 48  | 
val initial_levels = level_map(graph)  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
49  | 
|
| 49744 | 50  | 
val (dummy_graph, dummies, dummy_levels) =  | 
| 
56372
 
fadb0fef09d7
more explicit iterator terminology, in accordance to Scala 2.8 library;
 
wenzelm 
parents: 
50474 
diff
changeset
 | 
51  | 
        ((graph, Map.empty[(Key, Key), List[Key]], initial_levels) /: graph.keys_iterator) {
 | 
| 49744 | 52  | 
case ((graph, dummies, levels), from) =>  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
53  | 
            ((graph, dummies, levels) /: graph.imm_succs(from)) {
 | 
| 49744 | 54  | 
case ((graph, dummies, levels), to) =>  | 
55  | 
if (levels(to) - levels(from) <= 1) (graph, dummies, levels)  | 
|
| 50469 | 56  | 
                else {
 | 
57  | 
val (next, ds, ls) = add_dummies(graph, from, to, levels)  | 
|
58  | 
(next, dummies + ((from, to) -> ds), ls)  | 
|
59  | 
}  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
60  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
61  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
62  | 
|
| 50469 | 63  | 
val levels = minimize_crossings(dummy_graph, level_list(dummy_levels))  | 
64  | 
||
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
65  | 
val initial_coordinates: Coordinates =  | 
| 
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
66  | 
        (((Map.empty[Key, Point], 0.0) /: levels) {
 | 
| 
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
67  | 
case ((coords1, y), level) =>  | 
| 
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
68  | 
            ((((coords1, 0.0) /: level) {
 | 
| 59262 | 69  | 
case ((coords2, x), key) => (coords2 + (key -> Point(x, y)), x + box_distance)  | 
| 59260 | 70  | 
})._1, y + box_height(level))  | 
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
71  | 
})._1  | 
| 
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
72  | 
|
| 
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
73  | 
val coords = pendulum(dummy_graph, box_distance, levels, initial_coordinates)  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
74  | 
|
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
75  | 
val dummy_coords =  | 
| 50467 | 76  | 
        (Map.empty[(Key, Key), List[Point]] /: dummies.keys) {
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
77  | 
case (map, key) => map + (key -> dummies(key).map(coords(_)))  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
78  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
79  | 
|
| 59262 | 80  | 
new Layout(coords, dummy_coords)  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
81  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
82  | 
}  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
83  | 
|
| 49744 | 84  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
85  | 
def add_dummies(graph: Graph_Display.Graph, from: Key, to: Key, levels: Map[Key, Int])  | 
| 
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
86  | 
: (Graph_Display.Graph, List[Key], Map[Key, Int]) =  | 
| 49744 | 87  | 
  {
 | 
88  | 
val ds =  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
89  | 
      ((levels(from) + 1) until levels(to)).map(l => {
 | 
| 
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
90  | 
// FIXME !?  | 
| 
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
91  | 
val ident = "%s$%s$%d".format(from.ident, to.ident, l)  | 
| 
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
92  | 
Graph_Display.Node(ident, ident)  | 
| 
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
93  | 
}).toList  | 
| 49744 | 94  | 
|
95  | 
val ls =  | 
|
96  | 
      (levels /: ((levels(from) + 1) until levels(to)).zip(ds)) {
 | 
|
97  | 
case (ls, (l, d)) => ls + (d -> l)  | 
|
98  | 
}  | 
|
99  | 
||
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
100  | 
val graph1 = (graph /: ds)(_.new_node(_, Nil))  | 
| 49744 | 101  | 
val graph2 =  | 
102  | 
      (graph1.del_edge(from, to) /: (from :: ds ::: List(to)).sliding(2)) {
 | 
|
103  | 
case (g, List(x, y)) => g.add_edge(x, y)  | 
|
104  | 
}  | 
|
105  | 
(graph2, ds, ls)  | 
|
106  | 
}  | 
|
107  | 
||
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
108  | 
def level_map(graph: Graph_Display.Graph): Map[Key, Int] =  | 
| 50467 | 109  | 
    (Map.empty[Key, Int] /: graph.topological_order) {
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
110  | 
      (levels, key) => {
 | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
111  | 
        val lev = 1 + (-1 /: graph.imm_preds(key)) { case (m, key) => m max levels(key) }
 | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
112  | 
levels + (key -> lev)  | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
113  | 
}  | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
114  | 
}  | 
| 50469 | 115  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
116  | 
def level_list(map: Map[Key, Int]): Levels =  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
117  | 
  {
 | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
118  | 
    val max_lev = (-1 /: map) { case (m, (_, l)) => m max l }
 | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
119  | 
val buckets = new Array[Level](max_lev + 1)  | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
120  | 
    for (l <- 0 to max_lev) { buckets(l) = Nil }
 | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
121  | 
    for ((key, l) <- map) { buckets(l) = key :: buckets(l) }
 | 
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
122  | 
buckets.iterator.map(_.sorted(Graph_Display.Node.Ordering)).toList  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
123  | 
}  | 
| 
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
124  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
125  | 
def count_crossings(graph: Graph_Display.Graph, levels: Levels): Int =  | 
| 49746 | 126  | 
  {
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
127  | 
    def in_level(ls: Levels): Int = ls match {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
128  | 
case List(top, bot) =>  | 
| 49746 | 129  | 
        top.iterator.zipWithIndex.map {
 | 
130  | 
case (outer_parent, outer_parent_index) =>  | 
|
131  | 
graph.imm_succs(outer_parent).iterator.map(bot.indexOf(_))  | 
|
132  | 
.map(outer_child =>  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
133  | 
(0 until outer_parent_index)  | 
| 49746 | 134  | 
.map(inner_parent =>  | 
135  | 
graph.imm_succs(top(inner_parent)).iterator.map(bot.indexOf(_))  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
136  | 
.filter(inner_child => outer_child < inner_child)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
137  | 
.size  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
138  | 
).sum  | 
| 49746 | 139  | 
).sum  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
140  | 
}.sum  | 
| 49746 | 141  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
142  | 
case _ => 0  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
143  | 
}  | 
| 49746 | 144  | 
|
145  | 
levels.iterator.sliding(2).map(ls => in_level(ls.toList)).sum  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
146  | 
}  | 
| 50469 | 147  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
148  | 
def minimize_crossings(graph: Graph_Display.Graph, levels: Levels): Levels =  | 
| 49745 | 149  | 
  {
 | 
| 50469 | 150  | 
def resort_level(parent: Level, child: Level, top_down: Boolean): Level =  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
151  | 
      child.map(k => {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
152  | 
val ps = if (top_down) graph.imm_preds(k) else graph.imm_succs(k)  | 
| 50469 | 153  | 
val weight =  | 
| 50468 | 154  | 
            (0.0 /: ps) { (w, p) => w + (0 max parent.indexOf(p)) } / (ps.size max 1)
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
155  | 
(k, weight)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
156  | 
}).sortBy(_._2).map(_._1)  | 
| 50469 | 157  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
158  | 
    def resort(levels: Levels, top_down: Boolean) = top_down match {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
159  | 
case true =>  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
160  | 
        (List[Level](levels.head) /: levels.tail) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
161  | 
(tops, bot) => resort_level(tops.head, bot, top_down) :: tops  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
162  | 
}.reverse  | 
| 50469 | 163  | 
|
164  | 
case false =>  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
165  | 
        (List[Level](levels.reverse.head) /: levels.reverse.tail) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
166  | 
(bots, top) => resort_level(bots.head, top, top_down) :: bots  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
167  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
168  | 
}  | 
| 50469 | 169  | 
|
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
170  | 
    ((levels, count_crossings(graph, levels), true) /: (1 to minimize_crossings_iterations)) {
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
171  | 
      case ((old_levels, old_crossings, top_down), _) => {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
172  | 
val new_levels = resort(old_levels, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
173  | 
val new_crossings = count_crossings(graph, new_levels)  | 
| 
49737
 
dd6fc7c9504a
avoid somewhat heavy rebuilding of SortedMap via map where plain iteration is sufficient;
 
wenzelm 
parents: 
49565 
diff
changeset
 | 
174  | 
if (new_crossings < old_crossings)  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
175  | 
(new_levels, new_crossings, !top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
176  | 
else  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
177  | 
(old_levels, old_crossings, !top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
178  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
179  | 
}._1  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
180  | 
}  | 
| 50469 | 181  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
182  | 
def pendulum(graph: Graph_Display.Graph, box_distance: Double,  | 
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
183  | 
levels: Levels, coords: Map[Key, Point]): Coordinates =  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
184  | 
  {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
185  | 
type Regions = List[List[Region]]  | 
| 50469 | 186  | 
|
187  | 
def iteration(regions: Regions, coords: Coordinates, top_down: Boolean)  | 
|
188  | 
: (Regions, Coordinates, Boolean) =  | 
|
189  | 
    {
 | 
|
190  | 
val (nextr, nextc, moved) =  | 
|
| 50467 | 191  | 
((List.empty[List[Region]], coords, false) /:  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
192  | 
       (if (top_down) regions else regions.reverse)) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
193  | 
        case ((tops, coords, prev_moved), bot) => {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
194  | 
val nextb = collapse(coords, bot, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
195  | 
val (nextc, this_moved) = deflect(coords, nextb, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
196  | 
(nextb :: tops, nextc, prev_moved || this_moved)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
197  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
198  | 
}  | 
| 50469 | 199  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
200  | 
(nextr.reverse, nextc, moved)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
201  | 
}  | 
| 50469 | 202  | 
|
203  | 
def collapse(coords: Coordinates, level: List[Region], top_down: Boolean): List[Region] =  | 
|
204  | 
    {
 | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
205  | 
if (level.size <= 1) level  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
206  | 
      else {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
207  | 
var next = level  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
208  | 
var regions_changed = true  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
209  | 
        while (regions_changed) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
210  | 
regions_changed = false  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
211  | 
          for (i <- (next.length to 1)) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
212  | 
val (r1, r2) = (next(i-1), next(i))  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
213  | 
val d1 = r1.deflection(coords, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
214  | 
val d2 = r2.deflection(coords, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
215  | 
|
| 50469 | 216  | 
if (// Do regions touch?  | 
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
217  | 
r1.distance(coords, r2) <= box_distance &&  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
218  | 
// Do they influence each other?  | 
| 50469 | 219  | 
(d1 <= 0 && d2 < d1 || d2 > 0 && d1 > d2 || d1 > 0 && d2 < 0))  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
220  | 
            {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
221  | 
regions_changed = true  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
222  | 
r1.nodes = r1.nodes ::: r2.nodes  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
223  | 
next = next.filter(next.indexOf(_) != i)  | 
| 50469 | 224  | 
}  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
225  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
226  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
227  | 
next  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
228  | 
}  | 
| 50469 | 229  | 
}  | 
230  | 
||
231  | 
def deflect(coords: Coordinates, level: List[Region], top_down: Boolean)  | 
|
232  | 
: (Coordinates, Boolean) =  | 
|
233  | 
    {
 | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
234  | 
      ((coords, false) /: (0 until level.length)) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
235  | 
        case ((coords, moved), i) => {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
236  | 
val r = level(i)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
237  | 
val d = r.deflection(coords, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
238  | 
            val offset = {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
239  | 
if (i == 0 && d <= 0) d  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
240  | 
else if (i == level.length - 1 && d >= 0) d  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
241  | 
              else if (d < 0) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
242  | 
val prev = level(i-1)  | 
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
243  | 
(-(r.distance(coords, prev) - box_distance)) max d  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
244  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
245  | 
              else {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
246  | 
val next = level(i+1)  | 
| 
50474
 
6ee044e2d1a7
initial layout coordinates more like old browser;
 
wenzelm 
parents: 
50470 
diff
changeset
 | 
247  | 
(r.distance(coords, next) - box_distance) min d  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
248  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
249  | 
}  | 
| 50469 | 250  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
251  | 
(r.move(coords, offset), moved || (d != 0))  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
252  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
253  | 
}  | 
| 50469 | 254  | 
}  | 
255  | 
||
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
256  | 
val regions = levels.map(level => level.map(new Region(graph, _)))  | 
| 50469 | 257  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
258  | 
    ((regions, coords, true, true) /: (1 to pendulum_iterations)) {
 | 
| 49746 | 259  | 
case ((regions, coords, top_down, moved), _) =>  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
260  | 
        if (moved) {
 | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
261  | 
val (nextr, nextc, m) = iteration(regions, coords, top_down)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
262  | 
(nextr, nextc, !top_down, m)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
263  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
264  | 
else (regions, coords, !top_down, moved)  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
265  | 
}._2  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
266  | 
}  | 
| 50469 | 267  | 
|
| 59261 | 268  | 
/*This is an auxiliary class which is used by the layout algorithm when  | 
269  | 
calculating coordinates with the "pendulum method". A "region" is a  | 
|
270  | 
group of nodes which "stick together".*/  | 
|
| 
59245
 
be4180f3c236
more formal Graph_Display.Node (with ordering) and Graph_Display.Edge;
 
wenzelm 
parents: 
59240 
diff
changeset
 | 
271  | 
private class Region(val graph: Graph_Display.Graph, node: Key)  | 
| 50469 | 272  | 
  {
 | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
273  | 
var nodes: List[Key] = List(node)  | 
| 50469 | 274  | 
|
| 59262 | 275  | 
def left(coords: Coordinates): Double = nodes.iterator.map(coords(_).x).min  | 
276  | 
def right(coords: Coordinates): Double = nodes.iterator.map(coords(_).x).max  | 
|
| 50469 | 277  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
278  | 
def distance(coords: Coordinates, to: Region): Double =  | 
| 50468 | 279  | 
math.abs(left(coords) - to.left(coords)) min  | 
280  | 
math.abs(right(coords) - to.right(coords))  | 
|
| 50469 | 281  | 
|
| 59257 | 282  | 
def deflection(coords: Coordinates, top_down: Boolean): Double =  | 
283  | 
      (for {
 | 
|
284  | 
k <- nodes.iterator  | 
|
| 59262 | 285  | 
x = coords(k).x  | 
| 59257 | 286  | 
as = if (top_down) graph.imm_preds(k) else graph.imm_succs(k)  | 
| 59262 | 287  | 
} yield as.iterator.map(coords(_).x - x).sum / (as.size max 1)).sum / nodes.length  | 
| 50469 | 288  | 
|
| 59262 | 289  | 
def move(coords: Coordinates, dx: Double): Coordinates =  | 
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
290  | 
      (coords /: nodes) {
 | 
| 50469 | 291  | 
case (cs, node) =>  | 
| 59262 | 292  | 
val p = cs(node)  | 
293  | 
cs + (node -> Point(p.x + dx, p.y))  | 
|
| 
49557
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
294  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
295  | 
}  | 
| 
 
61988f9df94d
added Graphview tool, based on Isabelle/Scala and Swing/Graphics2D;
 
Markus Kaiser <markus.kaiser@in.tum.de> 
parents:  
diff
changeset
 | 
296  | 
}  | 
| 59262 | 297  | 
|
298  | 
final class Layout private(  | 
|
299  | 
nodes: Map[Graph_Display.Node, Layout.Point],  | 
|
300  | 
dummies: Map[Graph_Display.Edge, List[Layout.Point]])  | 
|
301  | 
{
 | 
|
302  | 
def get_node(node: Graph_Display.Node): Layout.Point =  | 
|
303  | 
nodes.getOrElse(node, Layout.Point.zero)  | 
|
304  | 
||
305  | 
def map_node(node: Graph_Display.Node, f: Layout.Point => Layout.Point): Layout =  | 
|
306  | 
    nodes.get(node) match {
 | 
|
307  | 
case None => this  | 
|
308  | 
case Some(p) => new Layout(nodes + (node -> f(p)), dummies)  | 
|
309  | 
}  | 
|
310  | 
||
311  | 
||
312  | 
def get_dummies(edge: Graph_Display.Edge): List[Layout.Point] =  | 
|
313  | 
dummies.getOrElse(edge, Nil)  | 
|
314  | 
||
315  | 
def map_dummies(edge: Graph_Display.Edge, f: List[Layout.Point] => List[Layout.Point]): Layout =  | 
|
316  | 
    dummies.get(edge) match {
 | 
|
317  | 
case None => this  | 
|
318  | 
case Some(ds) => new Layout(nodes, dummies + (edge -> f(ds)))  | 
|
319  | 
}  | 
|
320  | 
}  | 
|
321  |