/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.graph.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import junit.framework.TestCase; import org.geotools.graph.GraphTestUtil; import org.geotools.graph.build.GraphGenerator; import org.geotools.graph.build.basic.BasicGraphGenerator; import org.geotools.graph.structure.Edge; import org.geotools.graph.structure.GraphVisitor; import org.geotools.graph.structure.Graphable; import org.geotools.graph.structure.Node; import org.geotools.graph.util.graph.GraphFuser; public class GraphFuserTest extends TestCase { private GraphGenerator m_gen; public GraphFuserTest(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); m_gen = createGenerator(); } /** * Create a no bifurcation graph and fuse it. <BR> * <BR> * Expected: 1. Resulting graph should only have 2 nodes and 1 edge. <BR> * <BR> * O---O---O-...-O---O---O ==FUSER=> O-------...-------O * */ public void test_0() { final int nnodes = 100; Node[] ends = GraphTestUtil.buildNoBifurcations(generator(), nnodes); GraphGenerator fused = createGenerator(); GraphFuser fuser = new GraphFuser( generator().getGraph(), generator().getGraphBuilder(), createEdgeMerger() ); assertTrue(fuser.fuse()); assertTrue(generator().getGraph().getNodes().size() == 2); assertTrue(generator().getGraph().getEdges().size() == 1); GraphVisitor visitor = new GraphVisitor() { public int visit(Graphable component) { String id = (String)component.getObject(); assertTrue(id.equals("0") || id.equals(String.valueOf(nnodes-1))); return(0); } }; generator().getGraph().visitNodes(visitor); visitor = new GraphVisitor() { public int visit(Graphable component) { Edge e = (Edge)component; String id0 = (String)e.getNodeA().getObject(); String id1 = (String)e.getNodeB().getObject(); assertTrue( (id0.equals("0") && id1.equals(String.valueOf(nnodes-1)))|| (id0.equals(String.valueOf(nnodes-1)) && id1.equals("0")) ); return(0); } }; generator().getGraph().visitEdges(visitor); } /** * Build a no bifurcation graph and then add a cycle containing two adjacent * nodes and fuse. <BR> * <BR> * Expected: 1. The graph should have 4 nodes and 4 edges. <BR> * <BR> * ___ ___ * / \ / \ * O---O-...-O O-...-O---O ==FUSER=> O--...--O O--...--O * \___/ \___/ * */ public void test_1() { final int nnodes = 100; final int cyc = 50; Node[] ends = GraphTestUtil.buildNoBifurcations(generator(), nnodes); generator().add(new Object[]{String.valueOf(cyc), String.valueOf(cyc+1)}); GraphGenerator fused = createGenerator(); GraphFuser fuser = new GraphFuser( generator().getGraph(), generator().getGraphBuilder(), createEdgeMerger() ); assertTrue(fuser.fuse()); assertTrue(generator().getGraph().getNodes().size() == 4); assertTrue(generator().getGraph().getEdges().size() == 4); GraphVisitor visitor = new GraphVisitor() { public int visit(Graphable component) { String id = (String)component.getObject(); assertTrue( (id.equals("0") || id.equals(String.valueOf(nnodes-1))) || (id.equals(String.valueOf(cyc)) || id.equals(String.valueOf(cyc+1))) ); return(0); } }; generator().getGraph().visitNodes(visitor); visitor = new GraphVisitor() { public int visit(Graphable component) { Edge e = (Edge)component; String id0 = (String)e.getNodeA().getObject(); String id1 = (String)e.getNodeB().getObject(); assertTrue( (id0.equals("0") && id1.equals(String.valueOf(cyc)))|| (id0.equals(String.valueOf(cyc)) && id1.equals("0"))|| (id0.equals(String.valueOf(cyc)) && id1.equals(String.valueOf(cyc+1)))|| (id0.equals(String.valueOf(cyc+1)) && id1.equals(String.valueOf(cyc)))|| (id0.equals(String.valueOf(cyc+1)) && id1.equals(String.valueOf(nnodes-1)))|| (id0.equals(String.valueOf(nnodes-1)) && id1.equals(String.valueOf(cyc+1))) ); return(0); } }; generator().getGraph().visitEdges(visitor); } /** * Create a graph with no bifurcations and a cycle between containing three * nodes and fuse it. <BR> * <BR> * Expected: 1. The graph should have 4 nodes and 4 edges. <BR> * <BR> * _____ _____ * / \ / \ * O---O-...-O---O---O-...-O---O ==FUSER=> O--...-O------O-...--O * */ public void test_2() { final int nnodes = 100; final int cyc = 50; Node[] ends = GraphTestUtil.buildNoBifurcations(generator(), nnodes); generator().add(new Object[]{String.valueOf(cyc), String.valueOf(cyc+2)}); GraphGenerator fused = createGenerator(); GraphFuser fuser = new GraphFuser( generator().getGraph(), generator().getGraphBuilder(), createEdgeMerger() ); assertTrue(fuser.fuse()); assertTrue(generator().getGraph().getNodes().size() == 4); assertTrue(generator().getGraph().getEdges().size() == 4); GraphVisitor visitor = new GraphVisitor() { public int visit(Graphable component) { String id = (String)component.getObject(); assertTrue( (id.equals("0") || id.equals(String.valueOf(nnodes-1))) || (id.equals(String.valueOf(cyc)) || id.equals(String.valueOf(cyc+2))) ); return(0); } }; generator().getGraph().visitNodes(visitor); visitor = new GraphVisitor() { public int visit(Graphable component) { Edge e = (Edge)component; String id0 = (String)e.getNodeA().getObject(); String id1 = (String)e.getNodeB().getObject(); assertTrue( (id0.equals("0") && id1.equals(String.valueOf(cyc)))|| (id0.equals(String.valueOf(cyc)) && id1.equals("0"))|| (id0.equals(String.valueOf(cyc)) && id1.equals(String.valueOf(cyc+2)))|| (id0.equals(String.valueOf(cyc+2)) && id1.equals(String.valueOf(cyc)))|| (id0.equals(String.valueOf(cyc+2)) && id1.equals(String.valueOf(nnodes-1)))|| (id0.equals(String.valueOf(nnodes-1)) && id1.equals(String.valueOf(cyc+2))) ); return(0); } }; generator().getGraph().visitEdges(visitor); } /** * Create a circular graph and fuse it. <BR> * <BR> * Expected: 1. The graph should have 1 node and 1 edge, a loop on one node. * */ public void test_3() { int nnodes = 100; GraphTestUtil.buildCircular(generator(), nnodes); GraphGenerator fused = createGenerator(); GraphFuser fuser = new GraphFuser( generator().getGraph(), generator().getGraphBuilder(), createEdgeMerger() ); assertTrue(fuser.fuse()); assertTrue(generator().getGraph().getNodes().size() == 1); assertTrue(generator().getGraph().getEdges().size() == 1); } protected GraphGenerator createGenerator() { return(new BasicGraphGenerator()); } protected GraphGenerator generator() { return(m_gen); } protected GraphFuser.EdgeMerger createEdgeMerger() { return ( new GraphFuser.EdgeMerger() { public Object merge(List edges) { ArrayList ends = new ArrayList(); for (Iterator itr = edges.iterator(); itr.hasNext();) { Edge edge = (Edge)itr.next(); if ( edge.getNodeA().getDegree()!=2 || edge.getNodeB().getDegree()!=2 ) ends.add(edge); } Object[] obj = new Object[2]; if (ends.size() == 2) { Edge end0 = (Edge)ends.get(0); Edge end1 = (Edge)ends.get(1); obj[0] = end0.getNodeA().getDegree() == 2 ? end0.getNodeB().getObject() : end0.getNodeA() .getObject(); obj[1] = end1.getNodeA().getDegree() == 2 ? end1.getNodeB().getObject() : end1.getNodeA() .getObject(); } else if (ends.size() == 0) { obj[0] = ((Edge)edges.get(0)).getNodeA().getObject(); obj[1] = ((Edge)edges.get(0)).getNodeA().getObject(); } else throw new IllegalStateException("Found " + ends.size() + " ends."); return(obj); } public void setMergedObject(Edge newEdge, Object merged) { newEdge.setObject(merged); } public void setMergedObject(Edge newEdge, Object merged, List edges) { newEdge.setObject(merged); } } ); } }