|
28 | 28 | import java.util.Map;
|
29 | 29 | import java.util.stream.Collectors;
|
30 | 30 |
|
31 |
| -import org.jgrapht.Graph; |
32 |
| -import org.jgrapht.graph.DefaultGraphType; |
33 |
| -import org.jgrapht.graph.builder.GraphTypeBuilder; |
34 |
| -import org.jgrapht.util.SupplierUtil; |
35 |
| -import org.jungrapht.visualization.layout.algorithms.EiglspergerLayoutAlgorithm; |
36 |
| -import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm; |
37 |
| -import org.jungrapht.visualization.layout.algorithms.SugiyamaLayoutAlgorithm; |
38 |
| -import org.jungrapht.visualization.layout.algorithms.TreeLayoutAlgorithm; |
39 |
| -import org.jungrapht.visualization.layout.algorithms.sugiyama.Layering; |
40 |
| -import org.jungrapht.visualization.layout.model.LayoutModel; |
41 |
| -import org.jungrapht.visualization.layout.model.Point; |
42 |
| -import org.jungrapht.visualization.layout.model.Rectangle; |
43 |
| - |
44 | 31 | import tlc2.tool.EvalControl;
|
45 | 32 | import tlc2.value.impl.FcnLambdaValue;
|
46 | 33 | import tlc2.value.impl.FcnRcdValue;
|
@@ -180,65 +167,72 @@ public static Value directedMultiGraph(final Value n, final Value e, final Value
|
180 | 167 | final SetEnumValue edges = (SetEnumValue) e.toSetEnum();
|
181 | 168 | final RecordValue opts = (RecordValue) o.toRcd();
|
182 | 169 |
|
183 |
| - // https://jgrapht.org/guide/UserOverview#graph-structures |
184 |
| - final Graph<Value, Integer> graph = GraphTypeBuilder |
185 |
| - .<Value, Integer>forGraphType(DefaultGraphType.directedMultigraph()) |
186 |
| - .edgeSupplier(SupplierUtil.createIntegerSupplier()).allowingSelfLoops(false).buildGraph(); |
187 |
| - |
188 |
| - ValueVec elems = nodes.elems; |
189 |
| - for (int i = 0; i < elems.size(); i++) { |
190 |
| - graph.addVertex(elems.elementAt(i)); |
191 |
| - } |
192 |
| - elems = edges.elems; |
193 |
| - for (int i = 0; i < elems.size(); i++) { |
194 |
| - TupleValue tuple = (TupleValue) elems.elementAt(i); |
195 |
| - graph.addEdge(tuple.elems[0], tuple.elems[1]); |
196 |
| - } |
197 |
| - |
198 |
| - // Layout |
199 |
| - final IntValue viewH = (IntValue) opts.apply(new StringValue("view_width"), EvalControl.Clear); |
200 |
| - final IntValue viewW = (IntValue) opts.apply(new StringValue("view_height"), EvalControl.Clear); |
201 |
| - final LayoutModel<Value> layoutModel = LayoutModel.<Value>builder().size(viewW.val, viewH.val).graph(graph) |
202 |
| - .build(); |
203 |
| - |
204 |
| - // Algorithm |
205 |
| - final StringValue algo = (StringValue) opts.apply(new StringValue("algo"), EvalControl.Clear); |
206 |
| - getAlgo(algo.val.toString(), opts).visit(layoutModel); |
207 |
| - |
208 |
| - // Get the node's coordinates from the algorithm. |
209 |
| - final Map <Value, Point> locations = layoutModel.getLocations(); |
210 |
| - |
211 |
| - // convert to TLC values. |
212 |
| - return new FcnRcdValue(locations.entrySet().stream() |
213 |
| - .collect(Collectors.toMap(entry -> entry.getKey(), entry -> point2Value(entry.getValue())))); |
| 170 | + return JUngraph.toGraph(nodes, edges, opts); |
214 | 171 | }
|
| 172 | + |
| 173 | + private static class JUngraph { |
| 174 | + |
| 175 | + private static Value toGraph(final SetEnumValue nodes, final SetEnumValue edges, final RecordValue opts) { |
| 176 | + // https://jgrapht.org/guide/UserOverview#graph-structures |
| 177 | + final org.jgrapht.Graph<Value, Integer> graph = org.jgrapht.graph.builder.GraphTypeBuilder |
| 178 | + .<Value, Integer>forGraphType(org.jgrapht.graph.DefaultGraphType.directedMultigraph()) |
| 179 | + .edgeSupplier(org.jgrapht.util.SupplierUtil.createIntegerSupplier()).allowingSelfLoops(false).buildGraph(); |
| 180 | + |
| 181 | + ValueVec elems = nodes.elems; |
| 182 | + for (int i = 0; i < elems.size(); i++) { |
| 183 | + graph.addVertex(elems.elementAt(i)); |
| 184 | + } |
| 185 | + elems = edges.elems; |
| 186 | + for (int i = 0; i < elems.size(); i++) { |
| 187 | + TupleValue tuple = (TupleValue) elems.elementAt(i); |
| 188 | + graph.addEdge(tuple.elems[0], tuple.elems[1]); |
| 189 | + } |
| 190 | + |
| 191 | + // Layout |
| 192 | + final IntValue viewH = (IntValue) opts.apply(new StringValue("view_width"), EvalControl.Clear); |
| 193 | + final IntValue viewW = (IntValue) opts.apply(new StringValue("view_height"), EvalControl.Clear); |
| 194 | + final org.jungrapht.visualization.layout.model.LayoutModel<Value> layoutModel = org.jungrapht.visualization.layout.model.LayoutModel.<Value>builder().size(viewW.val, viewH.val).graph(graph) |
| 195 | + .build(); |
215 | 196 |
|
216 |
| - private static Value point2Value(final Point p) { |
217 |
| - final int x = ((Double) p.x).intValue(); |
218 |
| - final int y = ((Double) p.y).intValue(); |
219 |
| - return new RecordValue(new UniqueString[] { UniqueString.of("x"), UniqueString.of("y") }, |
220 |
| - new Value[] { IntValue.gen(x), IntValue.gen(y) }, false); |
221 |
| - } |
| 197 | + // Algorithm |
| 198 | + final StringValue algo = (StringValue) opts.apply(new StringValue("algo"), EvalControl.Clear); |
| 199 | + JUngraph.getAlgo(algo.val.toString(), opts).visit(layoutModel); |
| 200 | + |
| 201 | + // Get the node's coordinates from the algorithm. |
| 202 | + final Map <Value, org.jungrapht.visualization.layout.model.Point> locations = layoutModel.getLocations(); |
| 203 | + |
| 204 | + // convert to TLC values. |
| 205 | + return new FcnRcdValue(locations.entrySet().stream() |
| 206 | + .collect(Collectors.toMap(entry -> entry.getKey(), entry -> JUngraph.point2Value(entry.getValue())))); |
| 207 | + } |
222 | 208 |
|
223 |
| - private static LayoutAlgorithm<Value> getAlgo(final String algo, final RecordValue opts) { |
224 |
| - final IntValue nodeH = (IntValue) opts.apply(new StringValue("node_width"), EvalControl.Clear); |
225 |
| - final IntValue nodeW = (IntValue) opts.apply(new StringValue("node_height"), EvalControl.Clear); |
| 209 | + private static Value point2Value(final org.jungrapht.visualization.layout.model.Point p) { |
| 210 | + final int x = ((Double) p.x).intValue(); |
| 211 | + final int y = ((Double) p.y).intValue(); |
| 212 | + return new RecordValue(new UniqueString[] { UniqueString.of("x"), UniqueString.of("y") }, |
| 213 | + new Value[] { IntValue.gen(x), IntValue.gen(y) }, false); |
| 214 | + } |
226 | 215 |
|
227 |
| - switch (algo) { |
228 |
| - case "Sugiyama": |
229 |
| - // https://github.com/tomnelson/jungrapht-visualization/blob/afd155bf0246e5185f054ba1429bbcfbd429292a/jungrapht-layout/src/main/java/org/jungrapht/visualization/layout/algorithms/sugiyama/Layering.java#L4-L7 |
230 |
| - String l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString(); |
231 |
| - return SugiyamaLayoutAlgorithm.<Value, Integer>edgeAwareBuilder() |
232 |
| - .layering(Layering.valueOf(l)).vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false) |
233 |
| - .build(); |
234 |
| - case "Eiglsperger": |
235 |
| - l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString(); |
236 |
| - return EiglspergerLayoutAlgorithm.<Value, Integer>edgeAwareBuilder() |
237 |
| - .layering(Layering.valueOf(l)).vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false) |
238 |
| - .build(); |
239 |
| - default: |
240 |
| - return TreeLayoutAlgorithm.<Value>builder() |
241 |
| - .vertexBoundsFunction(v -> Rectangle.of(-5, -5, nodeW.val, nodeH.val)).build(); |
| 216 | + private static org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm<Value> getAlgo(final String algo, final RecordValue opts) { |
| 217 | + final IntValue nodeH = (IntValue) opts.apply(new StringValue("node_width"), EvalControl.Clear); |
| 218 | + final IntValue nodeW = (IntValue) opts.apply(new StringValue("node_height"), EvalControl.Clear); |
| 219 | + |
| 220 | + switch (algo) { |
| 221 | + case "Sugiyama": |
| 222 | + // https://github.com/tomnelson/jungrapht-visualization/blob/afd155bf0246e5185f054ba1429bbcfbd429292a/jungrapht-layout/src/main/java/org/jungrapht/visualization/layout/algorithms/sugiyama/Layering.java#L4-L7 |
| 223 | + String l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString(); |
| 224 | + return org.jungrapht.visualization.layout.algorithms.SugiyamaLayoutAlgorithm.<Value, Integer>edgeAwareBuilder() |
| 225 | + .layering(org.jungrapht.visualization.layout.algorithms.sugiyama.Layering.valueOf(l)).vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false) |
| 226 | + .build(); |
| 227 | + case "Eiglsperger": |
| 228 | + l = ((StringValue) opts.apply(new StringValue("layering"), EvalControl.Clear)).val.toString(); |
| 229 | + return org.jungrapht.visualization.layout.algorithms.EiglspergerLayoutAlgorithm.<Value, Integer>edgeAwareBuilder() |
| 230 | + .layering(org.jungrapht.visualization.layout.algorithms.sugiyama.Layering.valueOf(l)).vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).threaded(false) |
| 231 | + .build(); |
| 232 | + default: |
| 233 | + return org.jungrapht.visualization.layout.algorithms.TreeLayoutAlgorithm.<Value>builder() |
| 234 | + .vertexBoundsFunction(v -> org.jungrapht.visualization.layout.model.Rectangle.of(-5, -5, nodeW.val, nodeH.val)).build(); |
| 235 | + } |
242 | 236 | }
|
243 | 237 | }
|
244 | 238 |
|
|
0 commit comments