/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.trickl.graph.planar;
import com.jgraph.components.labels.MultiLineVertexView;
import com.trickl.graph.Labeller;
import com.trickl.graph.edges.DirectedEdge;
import com.trickl.graph.edges.IntegerEdgeFactory;
import com.trickl.graph.ext.*;
import com.trickl.graph.planar.faces.IdFace;
import com.trickl.graph.planar.faces.IdFaceFactory;
import com.trickl.graph.planar.generate.PlanarCircleGraphGenerator;
import com.trickl.graph.vertices.IntegerVertexFactory;
import java.awt.geom.AffineTransform;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JScrollPane;
import junit.framework.Assert;
import org.jgraph.JGraph;
import org.jgraph.graph.DefaultCellViewFactory;
import org.jgraph.graph.GraphLayoutCache;
import org.jgraph.graph.PortView;
import org.jgraph.graph.VertexView;
import org.jgrapht.ext.ComponentAttributeProvider;
import org.jgrapht.ext.StringNameProvider;
import org.junit.Ignore;
import org.junit.Test;
/**
*
* @author tgee
*/
public class DualGraphFaceLabellerTest {
public DualGraphFaceLabellerTest() {
}
@Test
public void testEmptyGraphLabelling() {
PlanarGraph<Integer, Integer> graph = new DoublyConnectedEdgeList<Integer, Integer, IdFace>(new IntegerEdgeFactory<Integer>(), new IdFaceFactory());
DualGraphFaceLabeller<Integer, Integer> labeller = new DualGraphFaceLabeller<Integer, Integer>(graph);
int labelCount = labeller.getLabelCount();
// Ensure there is just one label, for the boundary face
Assert.assertEquals(1, labelCount);
}
@Test
public void testTrivialGraphLabelling() throws InterruptedException, InvocationTargetException {
DoublyConnectedEdgeList<Integer, Integer, Object> graph = new DoublyConnectedEdgeList<Integer, Integer, Object>(new IntegerEdgeFactory<Integer>(), Object.class);
IntegerVertexFactory vertexFactory = new IntegerVertexFactory();
ArrayList<Integer> vertices = new ArrayList<Integer>(3);
for (int i = 0; i < 3; ++i) {
Integer vertex = vertexFactory.createVertex();
graph.addVertex(vertex);
vertices.add(vertex);
}
// A triangle
graph.addEdge(vertices.get(0), vertices.get(1));
graph.addEdge(vertices.get(0), vertices.get(2));
graph.addEdge(vertices.get(1), vertices.get(2));
DualGraphFaceLabeller<Integer, Integer> labeller = new DualGraphFaceLabeller<Integer, Integer>(graph);
int labelCount = labeller.getLabelCount();
// Ensure two distinct labels are created (one for the inner face, one for the boundary face)
Assert.assertEquals(2, labelCount);
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(0), vertices.get(1))));
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(1), vertices.get(2))));
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(2), vertices.get(0))));
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(1), vertices.get(0))));
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(2), vertices.get(1))));
Assert.assertNotNull(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(0), vertices.get(2))));
Assert.assertTrue(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(0), vertices.get(1)))
!= labeller.getLabel(new DirectedEdge<Integer>(vertices.get(1), vertices.get(0))));
Assert.assertTrue(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(1), vertices.get(2)))
!= labeller.getLabel(new DirectedEdge<Integer>(vertices.get(2), vertices.get(1))));
Assert.assertTrue(labeller.getLabel(new DirectedEdge<Integer>(vertices.get(2), vertices.get(1)))
!= labeller.getLabel(new DirectedEdge<Integer>(vertices.get(1), vertices.get(2))));
Assert.assertEquals(3, labeller.getMembers(0).size());
Assert.assertEquals(3, labeller.getMembers(1).size());
// Visual Check
if (Boolean.parseBoolean(System.getProperty("visualTests"))) {
JGraph jGraph = getDisplayGraph(graph, new ChrobakPayneLayout<Integer, Integer>(graph), labeller);
JComponentWindow window = new JComponentWindow(new JScrollPane(jGraph));
window.showAndWait();
}
}
@Test
public void testSmallMaximalGraphLabelling() throws InterruptedException, InvocationTargetException {
DoublyConnectedEdgeList<Integer, Integer, Object> graph = new DoublyConnectedEdgeList<Integer, Integer, Object>(new IntegerEdgeFactory(), Object.class);
IntegerVertexFactory vertexFactory = new IntegerVertexFactory();
ArrayList<Integer> vertices = new ArrayList<Integer>(6);
for (int i = 0; i < 6; ++i) {
Integer vertex = vertexFactory.createVertex();
graph.addVertex(vertex);
vertices.add(vertex);
}
// A maximally connected group of five vertices
graph.addEdge(vertices.get(0), vertices.get(1));
graph.addEdge(vertices.get(0), vertices.get(2));
graph.addEdge(vertices.get(1), vertices.get(2), vertices.get(0), vertices.get(0));
graph.addEdge(vertices.get(1), vertices.get(3), vertices.get(0), null);
graph.addEdge(vertices.get(3), vertices.get(2), vertices.get(1), vertices.get(0));
graph.addEdge(vertices.get(3), vertices.get(0), vertices.get(1), vertices.get(1));
graph.addEdge(vertices.get(1), vertices.get(4), vertices.get(0), null);
graph.addEdge(vertices.get(4), vertices.get(3), vertices.get(1), vertices.get(0));
graph.addEdge(vertices.get(0), vertices.get(4), vertices.get(3), vertices.get(3));
graph.addEdge(vertices.get(4), vertices.get(5), vertices.get(0), null);
graph.addEdge(vertices.get(5), vertices.get(3), vertices.get(4), vertices.get(0));
graph.addEdge(vertices.get(0), vertices.get(5), vertices.get(3), vertices.get(3));
DualGraphFaceLabeller<Integer, Integer> labeller = new DualGraphFaceLabeller<Integer, Integer>(graph);
int labelCount = labeller.getLabelCount();
// Check that no adjacent faces have the same color
Assert.assertTrue(labelCount < 6);
for (Integer edge : graph.edgeSet()) {
int leftLabel = labeller.getLabel(new DirectedEdge<Integer>(graph.getEdgeSource(edge), graph.getEdgeTarget(edge)));
int rightLabel = labeller.getLabel(new DirectedEdge<Integer>(graph.getEdgeTarget(edge), graph.getEdgeSource(edge)));
Assert.assertNotSame(leftLabel, rightLabel);
}
if (Boolean.parseBoolean(System.getProperty("visualTests"))) {
JGraph jGraph = getDisplayGraph(graph, new ChrobakPayneLayout<Integer, Integer>(graph), labeller);
JComponentWindow window = new JComponentWindow(new JScrollPane(jGraph));
window.showAndWait();
}
}
@Test
public void testMediumRegularGraphLabelling() throws InterruptedException, InvocationTargetException {
DoublyConnectedEdgeList<Integer, Integer, Object> graph = new DoublyConnectedEdgeList<Integer, Integer, Object>(new IntegerEdgeFactory(), Object.class);
PlanarCircleGraphGenerator<Integer, Integer> generator = new PlanarCircleGraphGenerator<Integer, Integer>(37, 0.2);
generator.generateGraph(graph, new IntegerVertexFactory(), null);
DualGraphFaceLabeller<Integer, Integer> labeller = new DualGraphFaceLabeller<Integer, Integer>(graph);
int labelCount = labeller.getLabelCount();
// Check that no adjacent vertices have the same color
Assert.assertTrue(labelCount < 6);
for (Integer edge : graph.edgeSet()) {
int leftLabel = labeller.getLabel(new DirectedEdge<Integer>(graph.getEdgeSource(edge), graph.getEdgeTarget(edge)));
int rightLabel = labeller.getLabel(new DirectedEdge<Integer>(graph.getEdgeTarget(edge), graph.getEdgeSource(edge)));
Assert.assertNotSame(leftLabel, rightLabel);
}
// Visual Check
if (Boolean.parseBoolean(System.getProperty("visualTests"))) {
JGraph jGraph = getDisplayGraph(graph, new ChrobakPayneLayout<Integer, Integer>(graph), labeller);
JComponentWindow window = new JComponentWindow(new JScrollPane(jGraph));
window.showAndWait();
}
}
private JGraph getDisplayGraph(PlanarGraph<Integer, Integer> graph, PlanarLayout<Integer> layout, Labeller<DirectedEdge<Integer>> labeller)
throws InterruptedException, InvocationTargetException {
// Visual check
AffineTransform screenProjection = AffineTransform.getTranslateInstance(300, 300);
screenProjection.scale(100, -100); // Flip y-axis
Map<String, String> vertexAttributes = new HashMap<String, String>();
vertexAttributes.put("shape", "circle");
vertexAttributes.put("size", "5,5");
vertexAttributes.put("color", "#000000");
vertexAttributes.put("fillcolor", "#777777");
Map<String, String>[] labelAttributes = new Map[6];
for (int i = 0; i < 6; ++i) {
labelAttributes[i] = new HashMap<String, String>();
}
// Color vertices according to the label
labelAttributes[0].put("fillcolor", "#CC4444");
labelAttributes[1].put("fillcolor", "#44CC44");
labelAttributes[2].put("fillcolor", "#4444CC");
labelAttributes[3].put("fillcolor", "#AAAA44");
labelAttributes[4].put("fillcolor", "#44AAAA");
labelAttributes[5].put("fillcolor", "#AA44AA");
Map<Integer, ComponentAttributeProvider<DirectedEdge<Integer>>> labelAttributeProviders = new HashMap<Integer, ComponentAttributeProvider<DirectedEdge<Integer>>>();
for (int i = 0; i < 6; ++i) {
labelAttributeProviders.put(i, new FixedAttributeProvider(labelAttributes[i]));
}
JGraph jGraph = new JGraph(new JGraphModelAdapterExt(graph,
null, //new StringNameProvider(),
null,
null,
new PlanarLayoutPositionProvider(layout, screenProjection,
new FixedAttributeProvider(vertexAttributes)),
null,
new FaceLabellerAttributeProvider<Integer>(labeller, labelAttributeProviders)));
jGraph.setEnabled(false);
jGraph.setMinimumSize(jGraph.getPreferredSize());
GraphLayoutCache layoutCache = jGraph.getGraphLayoutCache();
layoutCache.setFactory(new DefaultCellViewFactory() {
@Override
protected VertexView createVertexView(Object v) {
if (v instanceof FaceCell) {
return new FaceView((FaceCell) v);
} else {
return new MultiLineVertexView(v);
}
}
});
layoutCache.reload();
return jGraph;
}
}