diff -Nru libjung-free-java-2.0.1+dfsg/AUTHORS libjung-free-java-2.1.1/AUTHORS --- libjung-free-java-2.0.1+dfsg/AUTHORS 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/AUTHORS 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ +JUNG was originally created in 2003 by (in alphabetical order): + +Danyel Fisher +Joshua O'Madadhain +Scott White + +Later contributors have included: + +Tom Nelson +Yan-Biao Boey +W. Giordano +Masanori Harada +Nathan Mittler +Jasper Voskuilen +John Yesberg + +Sponsoring organizations: +Regents of the University of California +Google, Inc. diff -Nru libjung-free-java-2.0.1+dfsg/CONTRIBUTING.md libjung-free-java-2.1.1/CONTRIBUTING.md --- libjung-free-java-2.0.1+dfsg/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/CONTRIBUTING.md 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,35 @@ +Contributing +============ + +If you would like to contribute code to the JUNG Project you can do so through +GitHub by forking the repository and sending a pull request. + +When submitting code, please make every effort to follow existing conventions +and style in order to keep the code as readable as possible. + +Where appropriate, please provide unit tests. Unit tests should be JUnit based +and should be added to `/jung//src/test/java`. + +Please make sure your code compiles by running `mvn clean test` which will +build and run the tests. All pull requests will be validated by Travis-ci +in any case and typically must pass before being merged. + +If you are adding or modifying files you should add the following copyright +statement in a language-appropriate comment at the top of the file: + +``` +/* + * Copyright (c) , the JUNG Project and the Regents of the University + * of California. All rights reserved. + * + * This software is open-source under the BSD license; see + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +``` + +All files will be released to users of JUNG under a BSD license + +Before your code can be accepted into the project you must sign the +[Individual Contributor License Agreement (CLA)][CLA]. + +[CLA]: https://cla-assistant.io/jrtom/jung diff -Nru libjung-free-java-2.0.1+dfsg/debian/changelog libjung-free-java-2.1.1/debian/changelog --- libjung-free-java-2.0.1+dfsg/debian/changelog 2021-01-05 00:30:43.000000000 +0000 +++ libjung-free-java-2.1.1/debian/changelog 2021-11-15 15:22:38.000000000 +0000 @@ -1,9 +1,35 @@ -libjung-free-java (2.0.1+dfsg-1.1) unstable; urgency=medium +libjung-free-java (2.1.1-1) unstable; urgency=medium - * Non maintainer upload by the Reproducible Builds team. - * No source change upload to rebuild on buildd with .buildinfo files. + [ Andreas Tille ] + * New upstream version (project continued at GitHub) + (Closes: #884379, LP:1727772) + * Adapt URLs + * Upstream does not include any JAI code more so nothing to remove in + Files-Excluded + * cme fix dpkg-control + * Point Vcs fields to salsa.debian.org + * Standards-Version: 4.6.0 (routine-update) + * debhelper-compat 13 (routine-update) + * Add salsa-ci file (routine-update) + * Rules-Requires-Root: no (routine-update) + * Trim trailing whitespace. + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + * Apply multi-arch hints. + + libjung-free-java-doc: Add Multi-Arch: foreign. + * Remove default debian/gbp.conf - -- Holger Levsen Tue, 05 Jan 2021 01:30:43 +0100 + [ Pierre Gruet ] + * Fixing the Maven build + * Having the doc properly built and installed + * Adding a Lintian override for the embedded javascript + * Fixing the dh_auto_clean rule + * Removing a now useless patch about commons-collections + * Stripping useless dependencies, dropping B-D-indep deps + * Adding myself as uploader + * Setting the classpaths of the build jars with javahelper + + -- Pierre Gruet Mon, 15 Nov 2021 16:22:38 +0100 libjung-free-java (2.0.1+dfsg-1) unstable; urgency=low diff -Nru libjung-free-java-2.0.1+dfsg/debian/compat libjung-free-java-2.1.1/debian/compat --- libjung-free-java-2.0.1+dfsg/debian/compat 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru libjung-free-java-2.0.1+dfsg/debian/control libjung-free-java-2.1.1/debian/control --- libjung-free-java-2.0.1+dfsg/debian/control 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/control 2021-11-15 15:22:38.000000000 +0000 @@ -1,26 +1,29 @@ Source: libjung-free-java Maintainer: Debian Med Packaging Team Uploaders: Michael R. Crusoe , - Olivier Sallou + Olivier Sallou , + Pierre Gruet Section: java Priority: optional -Build-Depends: debhelper (>= 9), +Build-Depends: debhelper-compat (= 13), + default-jdk, javahelper, - unzip -Build-Depends-Indep: default-jdk, - libcolt-free-java, - libcommons-collections4-java, - libvecmath-java -Standards-Version: 3.9.6 -Vcs-Browser: https://anonscm.debian.org/cgit/debian-med/libjung-java.git -Vcs-Git: git://anonscm.debian.org/debian-med/libjung-java.git -Homepage: http://jung.sourceforge.net/ + libguava-java, + libmaven-javadoc-plugin-java, + libmaven-dependency-plugin-java, + maven-debian-helper, + junit4 +Standards-Version: 4.6.0 +Vcs-Browser: https://salsa.debian.org/med-team/libjung-free-java +Vcs-Git: https://salsa.debian.org/med-team/libjung-free-java.git +Homepage: https://github.com/jrtom/jung +Rules-Requires-Root: no Package: libjung-free-java Architecture: all -Depends: ${java:Depends}, +Depends: ${maven:Depends}, ${misc:Depends} -Recommends: ${java:Recommends} +Recommends: ${maven:Recommends} Description: Java Universal Network/Graph Framework JUNG provides a common and extendible language for the modeling, analysis, and visualization of data that can be represented as a graph or network. @@ -51,9 +54,10 @@ Package: libjung-free-java-doc Architecture: all Section: doc -Depends: ${java:Depends}, +Depends: ${maven:DocDepends}, ${misc:Depends} Recommends: ${java:Recommends} +Multi-Arch: foreign Description: Java Universal Network/Graph Framework (documentation) JUNG provides a common and extendible language for the modeling, analysis, and visualization of data that can be represented as a graph or network. diff -Nru libjung-free-java-2.0.1+dfsg/debian/copyright libjung-free-java-2.1.1/debian/copyright --- libjung-free-java-2.0.1+dfsg/debian/copyright 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/copyright 2021-11-15 15:22:38.000000000 +0000 @@ -1,13 +1,9 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: JUNG -Source: http://sourceforge.net/projects/jung/files/jung/jung-2.0.1/jung2-2_0_1-sources.zip/download -Files-Excluded: jung-3d-2.0.1-sources.jar - jung-3d-demos-2.0.1-sources.jar - jung-jai-2.0.1-sources.jar - jung-jai-samples-2.0.1-sources.jar +Source: https://github.com/jrtom/jung/releases Files: * -Copyright: © 2003-2004, Regents of the University of California and the JUNG Project +Copyright: © 2003-2016, Regents of the University of California and the JUNG Project License: BSD-3-clause Files: debian/* diff -Nru libjung-free-java-2.0.1+dfsg/debian/gbp.conf libjung-free-java-2.1.1/debian/gbp.conf --- libjung-free-java-2.0.1+dfsg/debian/gbp.conf 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -[DEFAULT] -# The default name for the upstream branch is "upstream". -# Change it if the name is different (for instance, "master"). -upstream-branch = upstream -# The default name for the Debian branch is "master". -# Change it if the name is different (for instance, "debian/unstable"). -debian-branch = master -# gbp import-orig uses the following names for the upstream tags. -# Change the value if you are not using gbp import-orig -upstream-tag = upstream/%(version)s -# Always use pristine-tar. -pristine-tar = True diff -Nru libjung-free-java-2.0.1+dfsg/debian/javabuild libjung-free-java-2.1.1/debian/javabuild --- libjung-free-java-2.0.1+dfsg/debian/javabuild 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/javabuild 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -jung-api-2.0.1.jar jung-api-2.0.1-sources -jung-algorithms-2.0.1.jar jung-algorithms-2.0.1-sources -jung-graph-impl-2.0.1.jar jung-graph-impl-2.0.1-sources -jung-io-2.0.1.jar jung-io-2.0.1-sources -jung-visualization-2.0.1.jar jung-visualization-2.0.1-sources -jung-samples-2.0.1.jar jung-samples-2.0.1-sources diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-contrib-java.jlibs libjung-free-java-2.1.1/debian/libjung-contrib-java.jlibs --- libjung-free-java-2.0.1+dfsg/debian/libjung-contrib-java.jlibs 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-contrib-java.jlibs 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -jung-algorithms-contrib-2.0.1.jar -jung-io-contrib-2.0.1.jar diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.classpath libjung-free-java-2.1.1/debian/libjung-free-java.classpath --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.classpath 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java.classpath 2021-11-15 10:06:56.000000000 +0000 @@ -0,0 +1,6 @@ +usr/share/java/jung-algorithms.jar /usr/share/java/jung-api.jar +usr/share/java/jung-api.jar /usr/share/java/guava.jar +usr/share/java/jung-graph-impl.jar /usr/share/java/jung-api.jar +usr/share/java/jung-io.jar /usr/share/java/jung-algorithms.jar /usr/share/java/jung-api.jar +usr/share/java/jung-samples.jar /usr/share/java/jung-algorithms.jar /usr/share/java/jung-api.jar /usr/share/java/jung-graph-impl.jar /usr/share/java/jung-io.jar /usr/share/java/jung-visualization.jar +usr/share/java/jung-visualization.jar /usr/share/java/jung-algorithms.jar /usr/share/java/jung-api.jar /usr/share/java/jung-graph-impl.jar diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.doc-base libjung-free-java-2.1.1/debian/libjung-free-java-doc.doc-base --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.doc-base 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java-doc.doc-base 2021-11-14 20:54:36.000000000 +0000 @@ -0,0 +1,9 @@ +Document: libjung-free-java-doc +Title: API JavaDoc for libjung-free-java +Author: Regents of the University of California and the JUNG project +Abstract: This is the API JavaDoc for libjung-free-java +Section: Science/Biology + +Format: HTML +Index: /usr/share/doc/libjung-free-java/api/index-all.html +Files: /usr/share/doc/libjung-free-java/api/*.html /usr/share/doc/libjung-free-java/api/edu/uci/ics/jung/*/*.html /usr/share/doc/libjung-free-java/api/edu/uci/ics/jung/*/*/*.html /usr/share/doc/libjung-free-java/api/edu/uci/ics/jung/*/*/*/*.html diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.javadoc libjung-free-java-2.1.1/debian/libjung-free-java-doc.javadoc --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.javadoc 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java-doc.javadoc 2021-11-13 22:11:17.000000000 +0000 @@ -1 +1 @@ -internal /usr/share/doc/libjung-free-java/api +target/site/apidocs /usr/share/doc/libjung-free-java/api diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.lintian-overrides libjung-free-java-2.1.1/debian/libjung-free-java-doc.lintian-overrides --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java-doc.lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java-doc.lintian-overrides 2021-11-13 22:39:03.000000000 +0000 @@ -0,0 +1,4 @@ +# It would be too complicated to remove the javascript that is included in +# javadocs, see the discussion on Debian Java mailing list starting at +# https://lists.debian.org/debian-java/2018/06/msg00020.html. +embedded-javascript-library usr/share/doc/libjung-free-java/api/jquery/* * diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.jlibs libjung-free-java-2.1.1/debian/libjung-free-java.jlibs --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.jlibs 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java.jlibs 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -jung-api-2.0.1.jar -jung-algorithms-2.0.1.jar -jung-graph-impl-2.0.1.jar -jung-io-2.0.1.jar -jung-visualization-2.0.1.jar -jung-samples-2.0.1.jar diff -Nru libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.poms libjung-free-java-2.1.1/debian/libjung-free-java.poms --- libjung-free-java-2.0.1+dfsg/debian/libjung-free-java.poms 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/libjung-free-java.poms 2021-11-12 19:43:44.000000000 +0000 @@ -0,0 +1,34 @@ +# List of POM files for the package +# Format of this file is: +# [option]* +# where option can be: +# --ignore: ignore this POM and its artifact if any +# --ignore-pom: don't install the POM. To use on POM files that are created +# temporarily for certain artifacts such as Javadoc jars. [mh_install, mh_installpoms] +# --no-parent: remove the tag from the POM +# --package=: an alternative package to use when installing this POM +# and its artifact +# --has-package-version: to indicate that the original version of the POM is the same as the upstream part +# of the version for the package. +# --keep-elements=: a list of XML elements to keep in the POM +# during a clean operation with mh_cleanpom or mh_installpom +# --artifact=: path to the build artifact associated with this POM, +# it will be installed when using the command mh_install. [mh_install] +# --java-lib: install the jar into /usr/share/java to comply with Debian +# packaging guidelines +# --usj-name=: name to use when installing the library in /usr/share/java +# --usj-version=: version to use when installing the library in /usr/share/java +# --no-usj-versionless: don't install the versionless link in /usr/share/java +# --dest-jar=: the destination for the real jar. +# It will be installed with mh_install. [mh_install] +# --classifier=: Optional, the classifier for the jar. Empty by default. +# --site-xml=: Optional, the location for site.xml if it needs to be installed. +# Empty by default. [mh_install] +# +pom.xml +jung-algorithms/pom.xml --java-lib +jung-api/pom.xml --java-lib +jung-graph-impl/pom.xml --java-lib +jung-io/pom.xml --java-lib +jung-samples/pom.xml --java-lib +jung-visualization/pom.xml --java-lib diff -Nru libjung-free-java-2.0.1+dfsg/debian/maven.rules libjung-free-java-2.1.1/debian/maven.rules --- libjung-free-java-2.0.1+dfsg/debian/maven.rules 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/maven.rules 2021-11-12 21:37:05.000000000 +0000 @@ -0,0 +1,2 @@ + +junit junit * s/4.*/4.x/ * * diff -Nru libjung-free-java-2.0.1+dfsg/debian/patches/managing_test_dependency.patch libjung-free-java-2.1.1/debian/patches/managing_test_dependency.patch --- libjung-free-java-2.0.1+dfsg/debian/patches/managing_test_dependency.patch 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/patches/managing_test_dependency.patch 2021-11-12 21:55:56.000000000 +0000 @@ -0,0 +1,19 @@ +Description: Substituting old type "test-jar" with classifier "tests". + Discussed on https://github.com/mtommila/apfloat/issues/13 about + libapfloat-java, this seems to be a Debian-only issue. +Author: Pierre Gruet +Origin: https://sources.debian.org/src/libapfloat-java/1.10.1-1/debian/patches/managing_test_dependency.patch +Forwarded: not-needed +Last-Update: 2021-11-12 + +--- a/jung-graph-impl/pom.xml ++++ b/jung-graph-impl/pom.xml +@@ -20,7 +20,7 @@ + net.sf.jung + jung-api + ${project.version} +- test-jar ++ tests + test + + diff -Nru libjung-free-java-2.0.1+dfsg/debian/patches/missing_override_test_Predicate.patch libjung-free-java-2.1.1/debian/patches/missing_override_test_Predicate.patch --- libjung-free-java-2.0.1+dfsg/debian/patches/missing_override_test_Predicate.patch 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/patches/missing_override_test_Predicate.patch 2021-11-15 10:40:16.000000000 +0000 @@ -0,0 +1,137 @@ +Description: adding missing override of test in some classes, using the same + definition as in the parent interface in guava-libraries. + It seems there exists another Predicate class in guava-libraries, without the + test method to be overridden... +Author: Pierre Gruet +Forwarded: not-needed +Last-Update: 2021-11-13 + +--- a/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java ++++ b/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java +@@ -20,4 +20,9 @@ + Pair endpoints = context.graph.getEndpoints(context.element); + return endpoints.getFirst().equals(endpoints.getSecond()); + } ++ ++ @Override ++ public boolean test(Context,E> context) { ++ return apply(context); ++ } + } +--- a/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java ++++ b/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java +@@ -452,6 +452,11 @@ + public boolean apply(String str) { + return (str != null && str.toLowerCase().startsWith(tag)); + } ++ ++ @Override ++ public boolean test(String str) { ++ return apply(str); ++ } + } + + +@@ -478,6 +483,12 @@ + { + return (s != null && s.toLowerCase().endsWith("list")); + } ++ ++ @Override ++ public boolean test(String s) ++ { ++ return apply(s); ++ } + } + + /** +--- a/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java ++++ b/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java +@@ -179,6 +179,11 @@ + public boolean apply(Context,E> c) { + return c.graph.getEdgeType(c.element) == EdgeType.DIRECTED; + } ++ ++ @Override ++ public boolean test(Context,E> c) { ++ return apply(c); ++ } + + } + +@@ -189,6 +194,11 @@ + public boolean apply(Context,E> c) { + return c.graph.getEdgeType(c.element) == EdgeType.UNDIRECTED; + } ++ ++ @Override ++ public boolean test(Context,E> c) { ++ return apply(c); ++ } + + } + +@@ -207,4 +217,4 @@ + void setPickSupport(GraphElementAccessor pickSupport); + + +-} +\ No newline at end of file ++} +--- a/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java ++++ b/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java +@@ -972,6 +972,12 @@ + } + return false; + } ++ ++ @Override ++ public boolean test(Context,E> context) ++ { ++ return apply(context); ++ } + } + + private final static class VertexDisplayPredicate +@@ -1000,6 +1006,11 @@ + else + return true; + } ++ ++ @Override ++ public boolean test(Context,V> context) { ++ return apply(context); ++ } + } + + /** +--- a/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemo.java ++++ b/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemo.java +@@ -124,6 +124,12 @@ + public boolean apply(Object e) { + + return exclusions.contains(e); ++ } ++ ++ @Override ++ public boolean test(Object e) { ++ ++ return apply(e); + }}); + + +--- a/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java ++++ b/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java +@@ -144,6 +144,12 @@ + public boolean apply(Object e) { + + return exclusions.contains(e); ++ } ++ ++ @Override ++ public boolean test(Object e) { ++ ++ return apply(e); + }}); + + diff -Nru libjung-free-java-2.0.1+dfsg/debian/patches/omit_HypergraphTest.patch libjung-free-java-2.1.1/debian/patches/omit_HypergraphTest.patch --- libjung-free-java-2.0.1+dfsg/debian/patches/omit_HypergraphTest.patch 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/patches/omit_HypergraphTest.patch 2021-11-15 10:41:27.000000000 +0000 @@ -0,0 +1,29 @@ +Description: omitting HypergraphTest as it launches an initialization error + which I cannot understand more deeply. I only meet it using Debian build + tools, not within a classical Maven build. +Author: Pierre Gruet +Forwarded: not-needed +Last-Update: 2021-11-14 + +--- a/jung-graph-impl/pom.xml ++++ b/jung-graph-impl/pom.xml +@@ -29,4 +29,19 @@ + test + + ++ ++ ++ ++ ++ org.apache.maven.plugins ++ maven-surefire-plugin ++ ${surefire.plugin.version} ++ ++ ++ **/HypergraphTest.java ++ ++ ++ ++ ++ + diff -Nru libjung-free-java-2.0.1+dfsg/debian/patches/series libjung-free-java-2.1.1/debian/patches/series --- libjung-free-java-2.0.1+dfsg/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/patches/series 2021-11-14 22:21:19.000000000 +0000 @@ -0,0 +1,3 @@ +managing_test_dependency.patch +missing_override_test_Predicate.patch +omit_HypergraphTest.patch diff -Nru libjung-free-java-2.0.1+dfsg/debian/patches/use-apache-commons-collections libjung-free-java-2.1.1/debian/patches/use-apache-commons-collections --- libjung-free-java-2.0.1+dfsg/debian/patches/use-apache-commons-collections 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/patches/use-apache-commons-collections 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ -Description: Fix incompatibilities between collections15 and collection4 -Author: Michael R. Crusoe -Forwarded: no -Last-Updated: 2015-02-21 - -Inspired by -http://sources.debian.net/data/main/g/geogebra/4.0.34.0+dfsg1-3/debian/patches/use-apache-commons-collections.patch - -References include http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html -and http://commons.apache.org/proper/commons-collections/release_4_0.html - ---- a/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/scoring/PageRank.java -+++ b/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/scoring/PageRank.java -@@ -52,7 +52,7 @@ - * @param edge_weight the edge weights (transition probabilities) - * @param alpha the probability of taking a random jump to an arbitrary vertex - */ -- public PageRank(Hypergraph graph, Transformer edge_weight, double alpha) -+ public PageRank(Hypergraph graph, Transformer/**/ edge_weight, double alpha) - { - super(graph, edge_weight, ScoringUtils.getUniformRootPrior(graph.getVertices()), alpha); - } ---- a/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java -+++ b/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java -@@ -65,7 +65,7 @@ - public class DijkstraDistance implements Distance - { - protected Hypergraph g; -- protected Transformer nev; -+ protected Transformer/* */ nev; - protected Map sourceMap; // a map of source vertices to an instance of SourceData - protected boolean cached; - protected double max_distance; -@@ -81,7 +81,7 @@ - * @param nev the class responsible for returning weights for edges - * @param cached specifies whether the results are to be cached - */ -- public DijkstraDistance(Hypergraph g, Transformer nev, boolean cached) { -+ public DijkstraDistance(Hypergraph g, Transformer/**/ nev, boolean cached) { - this.g = g; - this.nev = nev; - this.sourceMap = new HashMap(); -@@ -98,7 +98,7 @@ - * @param g the graph on which distances will be calculated - * @param nev the class responsible for returning weights for edges - */ -- public DijkstraDistance(Hypergraph g, Transformer nev) { -+ public DijkstraDistance(Hypergraph g, Transformer/* */ nev) { - this(g, nev, true); - } - -@@ -198,7 +198,7 @@ - { - if (!sd.distances.containsKey(w)) - { -- double edge_weight = nev.transform(e).doubleValue(); -+ double edge_weight = ((Number) nev.transform(e)).doubleValue(); - if (edge_weight < 0) - throw new IllegalArgumentException("Edges weights must be non-negative"); - double new_dist = v_dist + edge_weight; ---- a/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java -+++ b/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java -@@ -69,9 +69,9 @@ - } - - @SuppressWarnings("unchecked") -- protected AbstractLayout(Graph graph, Transformer initializer) { -+ protected AbstractLayout(Graph graph, Transformer/**/ initializer) { - this.graph = graph; -- Transformer chain = -+ Transformer/**/ chain = - ChainedTransformer.chainedTransformer(initializer, CloneTransformer.cloneTransformer()); - this.locations = LazyMap.lazyMap(new HashMap(), (Transformer)chain); - initialized = true; -@@ -83,9 +83,9 @@ - } - - @SuppressWarnings("unchecked") -- protected AbstractLayout(Graph graph, Transformer initializer, Dimension size) { -+ protected AbstractLayout(Graph graph, Transformer/**/ initializer, Dimension size) { - this.graph = graph; -- Transformer chain = -+ Transformer/**/ chain = - ChainedTransformer.chainedTransformer(initializer, CloneTransformer.cloneTransformer()); - this.locations = LazyMap.lazyMap(new HashMap(), (Transformer)chain); - this.size = size; -@@ -139,11 +139,11 @@ - } - - @SuppressWarnings("unchecked") -- public void setInitializer(Transformer initializer) { -+ public void setInitializer(Transformer/**/ initializer) { - if(this.equals(initializer)) { - throw new IllegalArgumentException("Layout cannot be initialized with itself"); - } -- Transformer chain = -+ Transformer/**/ chain = - ChainedTransformer.chainedTransformer(initializer, CloneTransformer.cloneTransformer()); - this.locations = LazyMap.lazyMap(new HashMap(), (Transformer)chain); - initialized = true; ---- a/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java -+++ b/jung-algorithms-2.0.1-sources/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java -@@ -28,8 +28,8 @@ - - protected Graph graph; - protected Forest forest; -- protected Transformer weights = -- (Transformer)new ConstantTransformer(1.0); -+ protected Transformer/**/ weights = -+ ConstantTransformer.constantTransformer(1.0); - - /** - * create a Forest from the supplied Graph and supplied Factory, which ---- a/jung-visualization-2.0.1-sources/edu/uci/ics/jung/visualization/layout/CachingLayout.java -+++ b/jung-visualization-2.0.1-sources/edu/uci/ics/jung/visualization/layout/CachingLayout.java -@@ -39,8 +39,8 @@ - - public CachingLayout(Layout delegate) { - super(delegate); -- this.locationMap = LazyMap.decorate(new HashMap(), -- new ChainedTransformer(new Transformer[]{delegate, CloneTransformer.cloneTransformer()})); -+ this.locationMap = LazyMap.lazyMap(new HashMap(), -+ ChainedTransformer.chainedTransformer(new Transformer[]{delegate, CloneTransformer.cloneTransformer()})); - } - - @Override ---- a/jung-visualization-2.0.1-sources/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java -+++ b/jung-visualization-2.0.1-sources/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java -@@ -47,8 +47,8 @@ - - public ObservableCachingLayout(Layout delegate) { - super(delegate); -- this.locationMap = LazyMap.decorate(new HashMap(), -- new ChainedTransformer(new Transformer[]{delegate, CloneTransformer.cloneTransformer()})); -+ this.locationMap = LazyMap.lazyMap(new HashMap(), -+ ChainedTransformer.chainedTransformer(new Transformer[]{delegate, CloneTransformer.cloneTransformer()})); - } - - /** ---- a/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/ClusteringDemo.java -+++ b/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/ClusteringDemo.java -@@ -80,10 +80,10 @@ - // Factory> graphFactory; - - Map vertexPaints = -- LazyMap.decorate(new HashMap(), -+ LazyMap.lazyMap(new HashMap(), - new ConstantTransformer(Color.white)); - Map edgePaints = -- LazyMap.decorate(new HashMap(), -+ LazyMap.lazyMap(new HashMap(), - new ConstantTransformer(Color.blue)); - - public final Color[] similarColors = -@@ -154,7 +154,7 @@ - vv = new VisualizationViewer(layout); - vv.setBackground( Color.white ); - //Tell the renderer to use our own customized color rendering -- vv.getRenderContext().setVertexFillPaintTransformer(MapTransformer.getInstance(vertexPaints)); -+ vv.getRenderContext().setVertexFillPaintTransformer(MapTransformer.mapTransformer(vertexPaints)); - vv.getRenderContext().setVertexDrawPaintTransformer(new Transformer() { - public Paint transform(Number v) { - if(vv.getPickedVertexState().isPicked(v)) { -@@ -165,7 +165,7 @@ - } - }); - -- vv.getRenderContext().setEdgeDrawPaintTransformer(MapTransformer.getInstance(edgePaints)); -+ vv.getRenderContext().setEdgeDrawPaintTransformer(MapTransformer.mapTransformer(edgePaints)); - - vv.getRenderContext().setEdgeStrokeTransformer(new Transformer() { - protected final Stroke THIN = new BasicStroke(1); ---- a/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java -+++ b/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java -@@ -90,7 +90,7 @@ - vv.getRenderContext().setVertexLabelTransformer( - // this chains together Transformers so that the html tags - // are prepended to the toString method output -- new ChainedTransformer(new Transformer[]{ -+ ChainedTransformer.chainedTransformer(new Transformer[]{ - new ToStringLabeller(), - new Transformer() { - public String transform(String input) { ---- a/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/GraphEditorDemo.java -+++ b/jung-samples-2.0.1-sources/edu/uci/ics/jung/samples/GraphEditorDemo.java -@@ -146,11 +146,11 @@ - vv = new VisualizationViewer(layout); - vv.setBackground(Color.white); - -- vv.getRenderContext().setVertexLabelTransformer(MapTransformer.getInstance( -- LazyMap.decorate(new HashMap(), new ToStringLabeller()))); -+ vv.getRenderContext().setVertexLabelTransformer(MapTransformer.mapTransformer( -+ LazyMap.lazyMap(new HashMap(), new ToStringLabeller()))); - -- vv.getRenderContext().setEdgeLabelTransformer(MapTransformer.getInstance( -- LazyMap.decorate(new HashMap(), new ToStringLabeller()))); -+ vv.getRenderContext().setEdgeLabelTransformer(MapTransformer.mapTransformer( -+ LazyMap.lazyMap(new HashMap(), new ToStringLabeller()))); - - vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer()); - diff -Nru libjung-free-java-2.0.1+dfsg/debian/rules libjung-free-java-2.1.1/debian/rules --- libjung-free-java-2.0.1+dfsg/debian/rules 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/rules 2021-11-14 21:12:52.000000000 +0000 @@ -1,37 +1,13 @@ #!/usr/bin/make -f -DH_VERBOSE := 1 - -export JAVA_HOME=/usr/lib/jvm/default-java -export CLASSPATH=/usr/share/java/commons-collections4.jar:/usr/share/java/colt.jar:/usr/share/java/vecmath.jar:./jung-api-2.0.1.jar:./jung-algorithms-2.0.1.jar:./jung-visualization-2.0.1.jar:./jung-graph-impl-2.0.1.jar:./jung-io-2.0.1.jar - %: - dh $@ --with javahelper --parallel - -override_dh_clean: - rm -rf jung-3d-2.0.1-sources jung-3d-demos-2.0.1-sources jung-algorithms-2.0.1-sources - rm -rf jung-api-2.0.1-sources jung-graph-impl-2.0.1-sources jung-io-2.0.1-sources - rm -rf jung-samples-2.0.1-sources jung-visualization-2.0.1-sources - dh_clean - -override_dh_auto_build: unzip - for jar in *.jar; do cd $${jar%%.jar}; find . -type f | xargs sed -i -e \ - 's/org.apache.commons.collections15/org.apache.commons.collections4/' \ - -e 's/org.apache.commons.collections4.Buffer/java.util.Queue/' \ - -e 's/org.apache.commons.collections4.buffer.UnboundedFifoBuffer/java.util.LinkedList/' \ - -e 's/UnboundedFifoBuffer/LinkedList/' \ - -e 's/BuffergetInstance/CloneTransformer.cloneTransformer/' \ - -e 's/OrPredicate.getInstance/OrPredicate.orPredicate/' \ - -e 's/TruePredicate.getInstance/TruePredicate.truePredicate/' ; \ - cd ..; done; - patch -p1 < debian/patches/use-apache-commons-collections - dh_auto_build + dh $@ --buildsystem=maven --with javahelper -unzip: - for jar in *.jar; do mkdir $${jar%%.jar}; cd $${jar%%.jar}; \ - unzip ../$${jar}; cd ..; done +override_dh_auto_clean: + dh_auto_clean + -rm -rf */target + +override_jh_installjavadoc: + jh_installjavadoc + # Removing wrong doc-base.javadoc file generated by jh_installjavadoc + rm debian/libjung-free-java-doc.doc-base.javadoc diff -Nru libjung-free-java-2.0.1+dfsg/debian/salsa-ci.yml libjung-free-java-2.1.1/debian/salsa-ci.yml --- libjung-free-java-2.0.1+dfsg/debian/salsa-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/debian/salsa-ci.yml 2021-11-12 19:34:31.000000000 +0000 @@ -0,0 +1,4 @@ +--- +include: + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml diff -Nru libjung-free-java-2.0.1+dfsg/debian/upstream/metadata libjung-free-java-2.1.1/debian/upstream/metadata --- libjung-free-java-2.0.1+dfsg/debian/upstream/metadata 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/upstream/metadata 2021-11-12 19:34:31.000000000 +0000 @@ -1,12 +1,15 @@ +Bug-Database: https://github.com/jrtom/jung/issues +Bug-Submit: https://github.com/jrtom/jung/issues/new Reference: - Author: O’Madadhain, Joshua and Fisher, Danyel and Smyth, Padhraic and White, Scott and Boey, Yan-Biao - Title: Analysis and visualization of network data using JUNG - Journal: - Year: - Volume: - Number: - Pages: - DOI: - PMID: - URL: + Author: > + O’Madadhain, Joshua and Fisher, Danyel and Smyth, Padhraic and White, + Scott and Boey, Yan-Biao + Title: Analysis and visualization of network data using JUNG + Journal: Journal of Statistical Software + Year: 2005 + Volume: 10 + Number: 2 + Pages: 1-35 eprint: http://jung.sourceforge.net/doc/JUNG_journal.pdf +Repository: https://github.com/jrtom/jung.git +Repository-Browse: https://github.com/jrtom/jung diff -Nru libjung-free-java-2.0.1+dfsg/debian/watch libjung-free-java-2.1.1/debian/watch --- libjung-free-java-2.0.1+dfsg/debian/watch 2016-01-14 11:26:40.000000000 +0000 +++ libjung-free-java-2.1.1/debian/watch 2021-11-12 19:34:31.000000000 +0000 @@ -1,3 +1,3 @@ -version=3 -opts="repacksuffix=+dfsg,dversionmangle=s/\+dfsg//g" \ - http://sf.net/jung/jung2-(\d)_(\d)_(\d)-sources\.zip +version=4 + +https://github.com/jrtom/jung/releases .*/jung-@ANY_VERSION@@ARCHIVE_EXT@ diff -Nru libjung-free-java-2.0.1+dfsg/.gitignore libjung-free-java-2.1.1/.gitignore --- libjung-free-java-2.0.1+dfsg/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/.gitignore 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,25 @@ +#General +*.orig +~* +*~ +*.bak + +# Maven +target/ +*.ser +*.ec + +# IntelliJ Idea +.idea/ +out/ +*.ipr +*.iws +*.iml + +# Eclipse +.classpath +.project +.settings/ +.metadata/ +.factoryPath +bin/ diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/assembly.xml libjung-free-java-2.1.1/jung-algorithms/assembly.xml --- libjung-free-java-2.0.1+dfsg/jung-algorithms/assembly.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/assembly.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + dependencies + + tar.gz + + false + + + / + + + + + / + false + runtime + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/pom.xml libjung-free-java-2.1.1/jung-algorithms/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-algorithms/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,32 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-algorithms + JUNG - Algorithms + Algorithms for the JUNG project + + + + net.sf.jung + jung-api + ${project.version} + + + net.sf.jung + jung-graph-impl + ${project.version} + test + + + junit + junit + test + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,32 @@ + + + + + + + +Support for establishing and maintaining graph element equivalence (such as in blockmodeling). +

+In blockmodeling, groups of vertices are clustered together by similarity +(as if members of a "block" appearing on the diagonal of the graph's adjacency +matrix). +

+This support currently includes: +

    +
  • VertexPartition: A class that maintains information on a +division of the vertices of a graph into disjoint sets. +
  • StructurallyEquivalent: An algorithm that finds sets of vertices that are +structurally equivalent. +
+ +

+ + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/StructurallyEquivalent.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * Created on Jan 28, 2004 + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.blockmodel; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Identifies sets of structurally equivalent vertices in a graph. Vertices + * i and j are structurally equivalent iff the set of i's + * neighbors is identical to the set of j's neighbors, with the + * exception of i and j themselves. This algorithm finds all + * sets of equivalent vertices in O(V^2) time. + * + *

You can extend this class to have a different definition of equivalence (by + * overriding isStructurallyEquivalent), and may give it hints for + * accelerating the process by overriding canPossiblyCompare. + * (For example, in a bipartite graph, canPossiblyCompare may + * return false for vertices in + * different partitions. This function should be fast.) + * + * @author Danyel Fisher + */ +public class StructurallyEquivalent implements Function, VertexPartition> +{ + public VertexPartition apply(Graph g) + { + Set> vertex_pairs = getEquivalentPairs(g); + + Set> rv = new HashSet>(); + Map> intermediate = new HashMap>(); + for (Pair p : vertex_pairs) + { + Set res = intermediate.get(p.getFirst()); + if (res == null) + res = intermediate.get(p.getSecond()); + if (res == null) // we haven't seen this one before + res = new HashSet(); + res.add(p.getFirst()); + res.add(p.getSecond()); + intermediate.put(p.getFirst(), res); + intermediate.put(p.getSecond(), res); + } + rv.addAll(intermediate.values()); + + // pick up the vertices which don't appear in intermediate; they are + // singletons (equivalence classes of size 1) + Collection singletons = new ArrayList(g.getVertices()); + singletons.removeAll(intermediate.keySet()); + for (V v : singletons) + { + Set v_set = Collections.singleton(v); + intermediate.put(v, v_set); + rv.add(v_set); + } + + return new VertexPartition(g, intermediate, rv); + } + + /** + * For each vertex pair v, v1 in G, checks whether v and v1 are fully + * equivalent: meaning that they connect to the exact same vertices. (Is + * this regular equivalence, or whathaveyou?) + * + * @param g the graph whose equivalent pairs are to be generated + * @return a Set of Pairs of vertices, where all the vertices in the inner + * Pairs are equivalent. + */ + protected Set> getEquivalentPairs(Graph g) { + + Set> rv = new HashSet>(); + Set alreadyEquivalent = new HashSet(); + + List l = new ArrayList(g.getVertices()); + + for (V v1 : l) + { + if (alreadyEquivalent.contains(v1)) + continue; + + for (Iterator iterator = l.listIterator(l.indexOf(v1) + 1); iterator.hasNext();) { + V v2 = iterator.next(); + + if (alreadyEquivalent.contains(v2)) + continue; + + if (!canBeEquivalent(v1, v2)) + continue; + + if (isStructurallyEquivalent(g, v1, v2)) { + Pair p = new Pair(v1, v2); + alreadyEquivalent.add(v2); + rv.add(p); + } + } + } + + return rv; + } + + /** + * @param g the graph in which the structural equivalence comparison is to take place + * @param v1 the vertex to check for structural equivalence to v2 + * @param v2 the vertex to check for structural equivalence to v1 + * @return {@code true} if {@code v1}'s predecessors/successors are equal to + * {@code v2}'s predecessors/successors + */ + protected boolean isStructurallyEquivalent(Graph g, V v1, V v2) { + + if( g.degree(v1) != g.degree(v2)) { + return false; + } + + Set n1 = new HashSet(g.getPredecessors(v1)); + n1.remove(v2); + n1.remove(v1); + Set n2 = new HashSet(g.getPredecessors(v2)); + n2.remove(v1); + n2.remove(v2); + + Set o1 = new HashSet(g.getSuccessors(v1)); + Set o2 = new HashSet(g.getSuccessors(v2)); + o1.remove(v1); + o1.remove(v2); + o2.remove(v1); + o2.remove(v2); + + // this neglects self-loops and directed edges from 1 to other + boolean b = (n1.equals(n2) && o1.equals(o2)); + if (!b) + return b; + + // if there's a directed edge v1->v2 then there's a directed edge v2->v1 + b &= ( g.isSuccessor(v1, v2) == g.isSuccessor(v2, v1)); + + // self-loop check + b &= ( g.isSuccessor(v1, v1) == g.isSuccessor(v2, v2)); + + return b; + + } + + /** + * This is a space for optimizations. For example, for a bipartite graph, + * vertices from different partitions cannot possibly be equivalent. + * + * @param v1 the first vertex to compare + * @param v2 the second vertex to compare + * @return {@code true} if the vertices can be equivalent + */ + protected boolean canBeEquivalent(V v1, V v2) { + return true; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/blockmodel/VertexPartition.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Feb 3, 2004 + */ +package edu.uci.ics.jung.algorithms.blockmodel; + +import java.util.*; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * Maintains information about a vertex partition of a graph. + * This can be built from a map from vertices to vertex sets + * or from a collection of (disjoint) vertex sets, + * such as those created by various clustering methods. + */ +public class VertexPartition +{ + private Map> vertex_partition_map; + private Collection> vertex_sets; + private Graph graph; + + /** + * Creates an instance based on the specified graph and mapping from vertices + * to vertex sets, and generates a set of partitions based on this mapping. + * @param g the graph over which the vertex partition is defined + * @param partition_map the mapping from vertices to vertex sets (partitions) + */ + public VertexPartition(Graph g, Map> partition_map) + { + this.vertex_partition_map = Collections.unmodifiableMap(partition_map); + this.graph = g; + } + + /** + * Creates an instance based on the specified graph, vertex-set mapping, + * and set of disjoint vertex sets. The vertex-set mapping and vertex + * partitions must be consistent; that is, the mapping must reflect the + * division of vertices into partitions, and each vertex must appear in + * exactly one partition. + * @param g the graph over which the vertex partition is defined + * @param partition_map the mapping from vertices to vertex sets (partitions) + * @param vertex_sets the set of disjoint vertex sets + */ + public VertexPartition(Graph g, Map> partition_map, + Collection> vertex_sets) + { + this.vertex_partition_map = Collections.unmodifiableMap(partition_map); + this.vertex_sets = vertex_sets; + this.graph = g; + } + + /** + * Creates an instance based on the specified graph and set of disjoint vertex sets, + * and generates a vertex-to-partition map based on these sets. + * @param g the graph over which the vertex partition is defined + * @param vertex_sets the set of disjoint vertex sets + */ + public VertexPartition(Graph g, Collection> vertex_sets) + { + this.vertex_sets = vertex_sets; + this.graph = g; + } + + /** + * Returns the graph on which the partition is defined. + * @return the graph on which the partition is defined + */ + public Graph getGraph() + { + return graph; + } + + /** + * Returns a map from each vertex in the input graph to its partition. + * This map is generated if it does not already exist. + * @return a map from each vertex in the input graph to a vertex set + */ + public Map> getVertexToPartitionMap() + { + if (vertex_partition_map == null) + { + this.vertex_partition_map = new HashMap>(); + for (Set set : this.vertex_sets) + for (V v : set) + this.vertex_partition_map.put(v, set); + } + return vertex_partition_map; + } + + /** + * Returns a collection of vertex sets, where each vertex in the + * input graph is in exactly one set. + * This collection is generated based on the vertex-to-partition map + * if it does not already exist. + * @return a collection of vertex sets such that each vertex in the + * instance's graph is in exactly one set + */ + public Collection> getVertexPartitions() + { + if (vertex_sets == null) + { + this.vertex_sets = new HashSet>(); + this.vertex_sets.addAll(vertex_partition_map.values()); + } + return vertex_sets; + } + + /** + * @return the number of partitions. + */ + public int numPartitions() + { + return vertex_sets.size(); + } + + @Override + public String toString() + { + return "Partitions: " + vertex_partition_map; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/BicomponentClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,165 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Finds all biconnected components (bicomponents) of an undirected graph. + * A graph is a biconnected component if + * at least 2 vertices must be removed in order to disconnect the graph. (Graphs + * consisting of one vertex, or of two connected vertices, are also biconnected.) Biconnected + * components of three or more vertices have the property that every pair of vertices in the component + * are connected by two or more vertex-disjoint paths. + *

+ * Running time: O(|V| + |E|) where |V| is the number of vertices and |E| is the number of edges + * @see "Depth first search and linear graph algorithms by R. E. Tarjan (1972), SIAM J. Comp." + * + * @author Joshua O'Madadhain + */ +public class BicomponentClusterer implements Function, Set>> +{ + protected Map dfs_num; + protected Map high; + protected Map parents; + protected Stack stack; + protected int converse_depth; + + /** + * Constructs a new bicomponent finder + */ + public BicomponentClusterer() { + } + + /** + * Extracts the bicomponents from the graph. + * @param theGraph the graph whose bicomponents are to be extracted + * @return the ClusterSet of bicomponents + */ + public Set> apply(UndirectedGraph theGraph) + { + Set> bicomponents = new LinkedHashSet>(); + + if (theGraph.getVertices().isEmpty()) + return bicomponents; + + // initialize DFS number for each vertex to 0 + dfs_num = new HashMap(); + for (V v : theGraph.getVertices()) + { + dfs_num.put(v, 0); + } + + for (V v : theGraph.getVertices()) + { + if (dfs_num.get(v).intValue() == 0) // if we haven't hit this vertex yet... + { + high = new HashMap(); + stack = new Stack(); + parents = new HashMap(); + converse_depth = theGraph.getVertexCount(); + // find the biconnected components for this subgraph, starting from v + findBiconnectedComponents(theGraph, v, bicomponents); + + // if we only visited one vertex, this method won't have + // ID'd it as a biconnected component, so mark it as one + if (theGraph.getVertexCount() - converse_depth == 1) + { + Set s = new HashSet(); + s.add(v); + bicomponents.add(s); + } + } + } + + return bicomponents; + } + + /** + *

Stores, in bicomponents, all the biconnected + * components that are reachable from v. + * + *

The algorithm basically proceeds as follows: do a depth-first + * traversal starting from v, marking each vertex with + * a value that indicates the order in which it was encountered (dfs_num), + * and with + * a value that indicates the highest point in the DFS tree that is known + * to be reachable from this vertex using non-DFS edges (high). (Since it + * is measured on non-DFS edges, "high" tells you how far back in the DFS + * tree you can reach by two distinct paths, hence biconnectivity.) + * Each time a new vertex w is encountered, push the edge just traversed + * on a stack, and call this method recursively. If w.high is no greater than + * v.dfs_num, then the contents of the stack down to (v,w) is a + * biconnected component (and v is an articulation point, that is, a + * component boundary). In either case, set v.high to max(v.high, w.high), + * and continue. If w has already been encountered but is + * not v's parent, set v.high max(v.high, w.dfs_num) and continue. + * + *

(In case anyone cares, the version of this algorithm on p. 224 of + * Udi Manber's "Introduction to Algorithms: A Creative Approach" seems to be + * wrong: the stack should be initialized outside this method, + * (v,w) should only be put on the stack if w hasn't been seen already, + * and there's no real benefit to putting v on the stack separately: just + * check for (v,w) on the stack rather than v. Had I known this, I could + * have saved myself a few days. JRTOM) + * + * @param g the graph to check for biconnected components + * @param v the starting place for searching for biconnected components + * @param bicomponents storage for the biconnected components found by this algorithm + */ + protected void findBiconnectedComponents(UndirectedGraph g, V v, Set> bicomponents) + { + int v_dfs_num = converse_depth; + dfs_num.put(v, v_dfs_num); + converse_depth--; + high.put(v, v_dfs_num); + + for (V w : g.getNeighbors(v)) + { + int w_dfs_num = dfs_num.get(w).intValue();//get(w, dfs_num); + E vw = g.findEdge(v,w); + if (w_dfs_num == 0) // w hasn't yet been visited + { + parents.put(w, v); // v is w's parent in the DFS tree + stack.push(vw); + findBiconnectedComponents(g, w, bicomponents); + int w_high = high.get(w).intValue();//get(w, high); + if (w_high <= v_dfs_num) + { + // v disconnects w from the rest of the graph, + // i.e., v is an articulation point + // thus, everything between the top of the stack and + // v is part of a single biconnected component + Set bicomponent = new HashSet(); + E e; + do + { + e = stack.pop(); + bicomponent.addAll(g.getIncidentVertices(e)); + } + while (e != vw); + bicomponents.add(bicomponent); + } + high.put(v, Math.max(w_high, high.get(v).intValue())); + } + else if (w != parents.get(v)) // (v,w) is a back or a forward edge + high.put(v, Math.max(w_dfs_num, high.get(v).intValue())); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/EdgeBetweennessClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,109 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.BetweennessCentrality; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * An algorithm for computing clusters (community structure) in graphs based on edge betweenness. + * The betweenness of an edge is defined as the extent to which that edge lies along + * shortest paths between all pairs of nodes. + * + * This algorithm works by iteratively following the 2 step process: + *

    + *
  • Compute edge betweenness for all edges in current graph + *
  • Remove edge with highest betweenness + *
+ *

+ * Running time is: O(kmn) where k is the number of edges to remove, m is the total number of edges, and + * n is the total number of vertices. For very sparse graphs the running time is closer to O(kn^2) and for + * graphs with strong community structure, the complexity is even lower. + *

+ * This algorithm is a slight modification of the algorithm discussed below in that the number of edges + * to be removed is parameterized. + * @author Scott White + * @author Tom Nelson (converted to jung2) + * @see "Community structure in social and biological networks by Michelle Girvan and Mark Newman" + */ +public class EdgeBetweennessClusterer implements Function,Set>> { + private int mNumEdgesToRemove; + private Map> edges_removed; + + /** + * Constructs a new clusterer for the specified graph. + * @param numEdgesToRemove the number of edges to be progressively removed from the graph + */ + public EdgeBetweennessClusterer(int numEdgesToRemove) { + mNumEdgesToRemove = numEdgesToRemove; + edges_removed = new LinkedHashMap>(); + } + + /** + * Finds the set of clusters which have the strongest "community structure". + * The more edges removed the smaller and more cohesive the clusters. + * @param graph the graph + */ + public Set> apply(Graph graph) { + + if (mNumEdgesToRemove < 0 || mNumEdgesToRemove > graph.getEdgeCount()) { + throw new IllegalArgumentException("Invalid number of edges passed in."); + } + + edges_removed.clear(); + + for (int k=0;k bc = new BetweennessCentrality(graph); + E to_remove = null; + double score = 0; + for (E e : graph.getEdges()) + if (bc.getEdgeScore(e) > score) + { + to_remove = e; + score = bc.getEdgeScore(e); + } + edges_removed.put(to_remove, graph.getEndpoints(to_remove)); + graph.removeEdge(to_remove); + } + + WeakComponentClusterer wcSearch = new WeakComponentClusterer(); + Set> clusterSet = wcSearch.apply(graph); + + for (Map.Entry> entry : edges_removed.entrySet()) + { + Pair endpoints = entry.getValue(); + graph.addEdge(entry.getKey(), endpoints.getFirst(), endpoints.getSecond()); + } + return clusterSet; + } + + /** + * Retrieves the list of all edges that were removed + * (assuming extract(...) was previously called). + * The edges returned + * are stored in order in which they were removed. + * + * @return the edges in the original graph + */ + public List getEdgesRemoved() + { + return new ArrayList(edges_removed.keySet()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + + + +Mechanisms for identifying clusters in graphs. Where these clusters define disjoint sets of vertices, +they may be used to define a VertexPartition for more convenient manipulation of the vertex/set +relationships. + +Current clustering algorithms include: +

    +
  • BicomponentClusterer: finds all subsets of vertices for which at least +2 vertices must be removed in order to disconnect the induced subgraphs. +
  • EdgeBetweennessClusterer: identifies vertex clusters by removing the edges of the highest +'betweenness' scores (see the importance/scoring package). +
  • VoltageClusterer: Clusters vertices based on their ranks as +calculated by VoltageRanker. +
  • WeakComponentVertexClusterer: Clusters vertices based on their membership in weakly +connected components of a graph. +
+ + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/VoltageClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 12, 2004 + */ +package edu.uci.ics.jung.algorithms.cluster; + +import edu.uci.ics.jung.algorithms.scoring.VoltageScorer; +import edu.uci.ics.jung.algorithms.util.DiscreteDistribution; +import edu.uci.ics.jung.algorithms.util.KMeansClusterer; +import edu.uci.ics.jung.algorithms.util.KMeansClusterer.NotEnoughClustersException; +import edu.uci.ics.jung.graph.Graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +/** + *

Clusters vertices of a Graph based on their ranks as + * calculated by VoltageScorer. This algorithm is based on, + * but not identical with, the method described in the paper below. + * The primary difference is that Wu and Huberman assume a priori that the clusters + * are of approximately the same size, and therefore use a more complex + * method than k-means (which is used here) for determining cluster + * membership based on co-occurrence data. + * + *

The algorithm proceeds as follows: + *

    + *
  • first, generate a set of candidate clusters as follows: + *
      + *
    • pick (widely separated) vertex pair, run VoltageScorer + *
    • group the vertices in two clusters according to their voltages + *
    • store resulting candidate clusters + *
    + *
  • second, generate k-1 clusters as follows: + *
      + *
    • pick a vertex v as a cluster 'seed' + *
      (Wu/Huberman: most frequent vertex in candidate clusters) + *
    • calculate co-occurrence over all candidate clusters of v with each other + * vertex + *
    • separate co-occurrence counts into high/low; + * high vertices constitute a cluster + *
    • remove v's vertices from candidate clusters; continue + *
    + *
  • finally, remaining unassigned vertices are assigned to the kth ("garbage") + * cluster. + *
+ * + *

NOTE: Depending on how the co-occurrence data splits the data into + * clusters, the number of clusters returned by this algorithm may be less than the + * number of clusters requested. The number of clusters will never be more than + * the number requested, however. + * + * @author Joshua O'Madadhain + * @see "'Finding communities in linear time: a physics approach', Fang Wu and Bernardo Huberman, http://www.hpl.hp.com/research/idl/papers/linear/" + * @see VoltageScorer + * @see KMeansClusterer + */ +public class VoltageClusterer +{ + protected int num_candidates; + protected KMeansClusterer kmc; + protected Random rand; + protected Graph g; + + /** + * Creates an instance of a VoltageCluster with the specified parameters. + * These are mostly parameters that are passed directly to VoltageScorer + * and KMeansClusterer. + * + * @param g the graph whose vertices are to be clustered + * @param num_candidates the number of candidate clusters to create + */ + public VoltageClusterer(Graph g, int num_candidates) + { + if (num_candidates < 1) + throw new IllegalArgumentException("must generate >=1 candidates"); + + this.num_candidates = num_candidates; + this.kmc = new KMeansClusterer(); + rand = new Random(); + this.g = g; + } + + protected void setRandomSeed(int random_seed) + { + rand = new Random(random_seed); + } + + /** + * @param v the vertex whose community we wish to discover + * @return a community (cluster) centered around v. + */ + public Collection> getCommunity(V v) + { + return cluster_internal(v, 2); + } + + /** + * Clusters the vertices of g into + * num_clusters clusters, based on their connectivity. + * @param num_clusters the number of clusters to identify + * @return a collection of clusters (sets of vertices) + */ + public Collection> cluster(int num_clusters) + { + return cluster_internal(null, num_clusters); + } + + /** + * Does the work of getCommunity and cluster. + * @param origin the vertex around which clustering is to be done + * @param num_clusters the (maximum) number of clusters to find + * @return a collection of clusters (sets of vertices) + */ + protected Collection> cluster_internal(V origin, int num_clusters) + { + // generate candidate clusters + // repeat the following 'samples' times: + // * pick (widely separated) vertex pair, run VoltageScorer + // * use k-means to identify 2 communities in ranked graph + // * store resulting candidate communities + ArrayList v_array = new ArrayList(g.getVertices()); + + LinkedList> candidates = new LinkedList>(); + + for (int j = 0; j < num_candidates; j++) + { + V source; + if (origin == null) + source = v_array.get((int)(rand.nextDouble() * v_array.size())); + else + source = origin; + V target = null; + do + { + target = v_array.get((int)(rand.nextDouble() * v_array.size())); + } + while (source == target); + VoltageScorer vs = new VoltageScorer(g, source, target); + vs.evaluate(); + + Map voltage_ranks = new HashMap(); + for (V v : g.getVertices()) + voltage_ranks.put(v, new double[] {vs.getVertexScore(v)}); + +// addOneCandidateCluster(candidates, voltage_ranks); + addTwoCandidateClusters(candidates, voltage_ranks); + } + + // repeat the following k-1 times: + // * pick a vertex v as a cluster seed + // (Wu/Huberman: most frequent vertex in candidates) + // * calculate co-occurrence (in candidate clusters) + // of this vertex with all others + // * use k-means to separate co-occurrence counts into high/low; + // high vertices are a cluster + // * remove v's vertices from candidate clusters + + Collection> clusters = new LinkedList>(); + Set remaining = new HashSet(g.getVertices()); + + List seed_candidates = getSeedCandidates(candidates); + int seed_index = 0; + + for (int j = 0; j < (num_clusters - 1); j++) + { + if (remaining.isEmpty()) + break; + + V seed; + if (seed_index == 0 && origin != null) + seed = origin; + else + { + do { seed = seed_candidates.get(seed_index++); } + while (!remaining.contains(seed)); + } + + Map occur_counts = getObjectCounts(candidates, seed); + if (occur_counts.size() < 2) + break; + + // now that we have the counts, cluster them... + try + { + Collection> high_low = kmc.cluster(occur_counts, 2); + // ...get the cluster with the highest-valued centroid... + Iterator> h_iter = high_low.iterator(); + Map cluster1 = h_iter.next(); + Map cluster2 = h_iter.next(); + double[] centroid1 = DiscreteDistribution.mean(cluster1.values()); + double[] centroid2 = DiscreteDistribution.mean(cluster2.values()); + Set new_cluster; + if (centroid1[0] >= centroid2[0]) + new_cluster = cluster1.keySet(); + else + new_cluster = cluster2.keySet(); + + // ...remove the elements of new_cluster from each candidate... + for (Set cluster : candidates) + cluster.removeAll(new_cluster); + clusters.add(new_cluster); + remaining.removeAll(new_cluster); + } + catch (NotEnoughClustersException nece) + { + // all remaining vertices are in the same cluster + break; + } + } + + // identify remaining vertices (if any) as a 'garbage' cluster + if (!remaining.isEmpty()) + clusters.add(remaining); + + return clusters; + } + + /** + * Do k-means with three intervals and pick the smaller two clusters + * (presumed to be on the ends); this is closer to the Wu-Huberman method. + * @param candidates the list of clusters to populate + * @param voltage_ranks the voltage values for each vertex + */ + protected void addTwoCandidateClusters(LinkedList> candidates, + Map voltage_ranks) + { + try + { + List> clusters = new ArrayList>(kmc.cluster(voltage_ranks, 3)); + boolean b01 = clusters.get(0).size() > clusters.get(1).size(); + boolean b02 = clusters.get(0).size() > clusters.get(2).size(); + boolean b12 = clusters.get(1).size() > clusters.get(2).size(); + if (b01 && b02) + { + candidates.add(clusters.get(1).keySet()); + candidates.add(clusters.get(2).keySet()); + } + else if (!b01 && b12) + { + candidates.add(clusters.get(0).keySet()); + candidates.add(clusters.get(2).keySet()); + } + else if (!b02 && !b12) + { + candidates.add(clusters.get(0).keySet()); + candidates.add(clusters.get(1).keySet()); + } + } + catch (NotEnoughClustersException e) + { + // no valid candidates, continue + } + } + + /** + * alternative to addTwoCandidateClusters(): cluster vertices by voltages into 2 clusters. + * We only consider the smaller of the two clusters returned + * by k-means to be a 'true' cluster candidate; the other is a garbage cluster. + * @param candidates the list of clusters to populate + * @param voltage_ranks the voltage values for each vertex + */ + protected void addOneCandidateCluster(LinkedList> candidates, + Map voltage_ranks) + { + try + { + List> clusters; + clusters = new ArrayList>(kmc.cluster(voltage_ranks, 2)); + if (clusters.get(0).size() < clusters.get(1).size()) + candidates.add(clusters.get(0).keySet()); + else + candidates.add(clusters.get(1).keySet()); + } + catch (NotEnoughClustersException e) + { + // no valid candidates, continue + } + } + + /** + * Returns a list of cluster seeds, ranked in decreasing order + * of number of appearances in the specified collection of candidate + * clusters. + * @param candidates the set of candidate clusters + * @return a set of cluster seeds + */ + protected List getSeedCandidates(Collection> candidates) + { + final Map occur_counts = getObjectCounts(candidates, null); + + ArrayList occurrences = new ArrayList(occur_counts.keySet()); + Collections.sort(occurrences, new MapValueArrayComparator(occur_counts)); + +// System.out.println("occurrences: "); + for (int i = 0; i < occurrences.size(); i++) + System.out.println(occur_counts.get(occurrences.get(i))[0]); + + return occurrences; + } + + protected Map getObjectCounts(Collection> candidates, V seed) + { + Map occur_counts = new HashMap(); + for (V v : g.getVertices()) + occur_counts.put(v, new double[]{0}); + + for (Set candidate : candidates) + { + if (seed == null) + System.out.println(candidate.size()); + if (seed == null || candidate.contains(seed)) + { + for (V element : candidate) + { + double[] count = occur_counts.get(element); + count[0]++; + } + } + } + + if (seed == null) + { + System.out.println("occur_counts size: " + occur_counts.size()); + for (V v : occur_counts.keySet()) + System.out.println(occur_counts.get(v)[0]); + } + + return occur_counts; + } + + protected class MapValueArrayComparator implements Comparator + { + private Map map; + + protected MapValueArrayComparator(Map map) + { + this.map = map; + } + + public int compare(V o1, V o2) + { + double[] count0 = map.get(o1); + double[] count1 = map.get(o2); + if (count0[0] < count1[0]) + return 1; + else if (count0[0] > count1[0]) + return -1; + return 0; + } + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * Finds all weak components in a graph as sets of vertex sets. A weak component is defined as + * a maximal subgraph in which all pairs of vertices in the subgraph are reachable from one + * another in the underlying undirected subgraph. + *

This implementation identifies components as sets of vertex sets. + * To create the induced graphs from any or all of these vertex sets, + * see algorithms.filters.FilterUtils. + *

+ * Running time: O(|V| + |E|) where |V| is the number of vertices and |E| is the number of edges. + * @author Scott White + */ +public class WeakComponentClusterer implements Function, Set>> +{ + /** + * Extracts the weak components from a graph. + * @param graph the graph whose weak components are to be extracted + * @return the list of weak components + */ + public Set> apply(Graph graph) { + + Set> clusterSet = new HashSet>(); + + HashSet unvisitedVertices = new HashSet(graph.getVertices()); + + while (!unvisitedVertices.isEmpty()) { + Set cluster = new HashSet(); + V root = unvisitedVertices.iterator().next(); + unvisitedVertices.remove(root); + cluster.add(root); + + Queue queue = new LinkedList(); + queue.add(root); + + while (!queue.isEmpty()) { + V currentVertex = queue.remove(); + Collection neighbors = graph.getNeighbors(currentVertex); + + for(V neighbor : neighbors) { + if (unvisitedVertices.contains(neighbor)) { + queue.add(neighbor); + unvisitedVertices.remove(neighbor); + cluster.add(neighbor); + } + } + } + clusterSet.add(cluster); + } + return clusterSet; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/EdgePredicateFilter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Created on May 19, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.filters; + +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Transforms the input graph into one which contains only those edges + * that pass the specified Predicate. The filtered graph + * is a copy of the original graph (same type, uses the same vertex and + * edge objects). All vertices from the original graph + * are copied into the new graph (even if they are not incident to any + * edges in the new graph). + * + * @author Joshua O'Madadhain + */ +public class EdgePredicateFilter implements Filter +{ + protected Predicate edge_pred; + + /** + * Creates an instance based on the specified edge Predicate. + * @param edge_pred the predicate that specifies which edges to add to the filtered graph + */ + public EdgePredicateFilter(Predicate edge_pred) + { + this.edge_pred = edge_pred; + } + + @SuppressWarnings("unchecked") + public Graph apply(Graph g) + { + Graph filtered; + try + { + filtered = g.getClass().newInstance(); + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + + for (V v : g.getVertices()) + filtered.addVertex(v); + + for (E e : g.getEdges()) + { + if (edge_pred.apply(e)) + filtered.addEdge(e, g.getIncidentVertices(e)); + } + + return filtered; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/Filter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.filters; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * An interface for classes that return a subset of the input Graph + * as a Graph. The Graph returned may be either a + * new graph or a view into an existing graph; the documentation for the filter + * must specify which. + * + * @author danyelf + */ +public interface Filter extends Function, Graph>{ } diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/FilterUtils.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jun 7, 2008 + * + */ +package edu.uci.ics.jung.algorithms.filters; + +import java.util.ArrayList; +import java.util.Collection; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Utility methods relating to filtering. + */ +public class FilterUtils +{ + /** + * Creates the induced subgraph from graph whose vertex set + * is equal to vertices. The graph returned has + * vertices as its vertex set, and includes all edges from + * graph which are incident only to elements of + * vertices. + * + * @param the vertex type + * @param the edge type + * @param the graph type + * @param vertices the subset of graph's vertices around + * which the subgraph is to be constructed + * @param graph the graph whose subgraph is to be constructed + * @return the subgraph induced by vertices + * @throws IllegalArgumentException if any vertex in + * vertices is not in graph + */ + @SuppressWarnings("unchecked") + public static > G createInducedSubgraph(Collection + vertices, G graph) + { + G subgraph = null; + try + { + subgraph = (G)graph.getClass().newInstance(); + + for (V v : vertices) + { + if (!graph.containsVertex(v)) + throw new IllegalArgumentException("Vertex " + v + + " is not an element of " + graph); + subgraph.addVertex(v); + } + + for (E e : graph.getEdges()) + { + Collection incident = graph.getIncidentVertices(e); + if (vertices.containsAll(incident)) + subgraph.addEdge(e, incident, graph.getEdgeType(e)); + } + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + return subgraph; + } + + /** + * Creates the induced subgraphs of graph associated with each + * element of vertex_collections. + * Note that these vertex collections need not be disjoint. + * @param the vertex type + * @param the edge type + * @param the graph type + * @param vertex_collections the collections of vertex collections to be + * used to induce the subgraphs + * @param graph the graph whose subgraphs are to be created + * @return the induced subgraphs of graph associated with each + * element of vertex_collections + */ + public static > Collection + createAllInducedSubgraphs(Collection> + vertex_collections, G graph) + { + Collection subgraphs = new ArrayList(); + + for (Collection vertex_set : vertex_collections) + subgraphs.add(createInducedSubgraph(vertex_set, graph)); + + return subgraphs; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/KNeighborhoodFilter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Dec 26, 2001 + * + */ +package edu.uci.ics.jung.algorithms.filters; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import edu.uci.ics.jung.algorithms.filters.Filter; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * A filter used to extract the k-neighborhood around one or more root node(s). + * The k-neighborhood is defined as the subgraph induced by the set of + * vertices that are k or fewer hops (unweighted shortest-path distance) + * away from the root node. + * + * @author Danyel Fisher + */ +public class KNeighborhoodFilter implements Filter { + + /** + * The type of edge to follow for defining the neighborhood. + */ + public static enum EdgeType { IN_OUT, IN, OUT } + private Set rootNodes; + private int radiusK; + private EdgeType edgeType; + + /** + * Constructs a new instance of the filter. + * @param rootNodes the set of root nodes + * @param radiusK the neighborhood radius around the root set + * @param edgeType 0 for in/out edges, 1 for in-edges, 2 for out-edges + */ + public KNeighborhoodFilter(Set rootNodes, int radiusK, EdgeType edgeType) { + this.rootNodes = rootNodes; + this.radiusK = radiusK; + this.edgeType = edgeType; + } + + /** + * Constructs a new instance of the filter. + * @param rootNode the root node + * @param radiusK the neighborhood radius around the root set + * @param edgeType 0 for in/out edges, 1 for in-edges, 2 for out-edges + */ + public KNeighborhoodFilter(V rootNode, int radiusK, EdgeType edgeType) { + this.rootNodes = new HashSet(); + this.rootNodes.add(rootNode); + this.radiusK = radiusK; + this.edgeType = edgeType; + } + + /** + * Constructs an unassembled graph containing the k-neighborhood around the root node(s). + */ + @SuppressWarnings("unchecked") + public Graph apply(Graph graph) { + // generate a Set of Vertices we want + // add all to the UG + int currentDepth = 0; + List currentVertices = new ArrayList(); + Set visitedVertices = new HashSet(); + Set visitedEdges = new HashSet(); + Set acceptedVertices = new HashSet(); + //Copy, mark, and add all the root nodes to the new subgraph + for (V currentRoot : rootNodes) { + + visitedVertices.add(currentRoot); + acceptedVertices.add(currentRoot); + currentVertices.add(currentRoot); + } + ArrayList newVertices = null; + //Use BFS to locate the neighborhood around the root nodes within distance k + while (currentDepth < radiusK) { + newVertices = new ArrayList(); + for (V currentVertex : currentVertices) { + + Collection edges = null; + switch (edgeType) { + case IN_OUT : + edges = graph.getIncidentEdges(currentVertex); + break; + case IN : + edges = graph.getInEdges(currentVertex); + break; + case OUT : + edges = graph.getOutEdges(currentVertex); + break; + } + for (E currentEdge : edges) { + + V currentNeighbor = + graph.getOpposite(currentVertex, currentEdge); + if (!visitedEdges.contains(currentEdge)) { + visitedEdges.add(currentEdge); + if (!visitedVertices.contains(currentNeighbor)) { + visitedVertices.add(currentNeighbor); + acceptedVertices.add(currentNeighbor); + newVertices.add(currentNeighbor); + } + } + } + } + currentVertices = newVertices; + currentDepth++; + } + Graph ug = null; + try { + ug = graph.getClass().newInstance(); + for(E edge : graph.getEdges()) { + Pair endpoints = graph.getEndpoints(edge); + if(acceptedVertices.containsAll(endpoints)) { + ug.addEdge(edge, endpoints.getFirst(), endpoints.getSecond()); + } + } + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + return ug; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,30 @@ + + + + + + + +Filtering mechanisms that produce subgraphs of an original graph. +Currently includes: +

    +
  • Filter: an interface for graph filters +
  • {Edge,Vertex}PredicateFilter: graph filters that return the +induced subgraph according to the +specified edge or vertex Predicate, respectively. +
  • KNeighborhoodFilter: a filter that returns the subgraph +induced by vertices within (unweighted) distance k of a specified vertex. +
+ + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/filters/VertexPredicateFilter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Created on May 19, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.filters; + +import java.util.Collection; + +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Transforms the input graph into one which contains only those vertices + * that pass the specified Predicate. The filtered graph + * is a copy of the original graph (same type, uses the same vertex and + * edge objects). Only those edges whose entire incident vertex collection + * passes the predicate are copied into the new graph. + * + * @author Joshua O'Madadhain + */ +public class VertexPredicateFilter implements Filter +{ + protected Predicate vertex_pred; + + /** + * Creates an instance based on the specified vertex Predicate. + * @param vertex_pred the predicate that specifies which vertices to add to the filtered graph + */ + public VertexPredicateFilter(Predicate vertex_pred) + { + this.vertex_pred = vertex_pred; + } + + @SuppressWarnings("unchecked") + public Graph apply(Graph g) + { + Graph filtered; + try + { + filtered = g.getClass().newInstance(); + } + catch (InstantiationException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException("Unable to create copy of existing graph: ", e); + } + + for (V v : g.getVertices()) + if (vertex_pred.apply(v)) + filtered.addVertex(v); + + Collection filtered_vertices = filtered.getVertices(); + + for (E e : g.getEdges()) + { + Collection incident = g.getIncidentVertices(e); + if (filtered_vertices.containsAll(incident)) + filtered.addEdge(e, incident); + } + + return filtered; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/EdmondsKarpMaxFlow.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,314 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.flows; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.util.IterativeProcess; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; + + +/** + * Implements the Edmonds-Karp maximum flow algorithm for solving the maximum flow problem. + * After the algorithm is executed, + * the input {@code Map} is populated with a {@code Number} for each edge that indicates + * the flow along that edge. + *

+ * An example of using this algorithm is as follows: + *

+ * EdmondsKarpMaxFlow ek = new EdmondsKarpMaxFlow(graph, source, sink, edge_capacities, edge_flows, 
+ * edge_factory);
+ * ek.evaluate(); // This instructs the class to compute the max flow
+ * 
+ * + * @see "Introduction to Algorithms by Cormen, Leiserson, Rivest, and Stein." + * @see "Network Flows by Ahuja, Magnanti, and Orlin." + * @see "Theoretical improvements in algorithmic efficiency for network flow problems by Edmonds and Karp, 1972." + * @author Scott White, adapted to jung2 by Tom Nelson + */ +public class EdmondsKarpMaxFlow extends IterativeProcess { + + private DirectedGraph mFlowGraph; + private DirectedGraph mOriginalGraph; + private V source; + private V target; + private int mMaxFlow; + private Set mSourcePartitionNodes; + private Set mSinkPartitionNodes; + private Set mMinCutEdges; + + private Map residualCapacityMap = new HashMap(); + private Map parentMap = new HashMap(); + private Map parentCapacityMap = new HashMap(); + private Function edgeCapacityTransformer; + private Map edgeFlowMap; + private Supplier edgeFactory; + + /** + * Constructs a new instance of the algorithm solver for a given graph, source, and sink. + * Source and sink vertices must be elements of the specified graph, and must be + * distinct. + * @param directedGraph the flow graph + * @param source the source vertex + * @param sink the sink vertex + * @param edgeCapacityTransformer the Function that gets the capacity for each edge. + * @param edgeFlowMap the map where the solver will place the value of the flow for each edge + * @param edgeFactory used to create new edge instances for backEdges + */ + @SuppressWarnings("unchecked") + public EdmondsKarpMaxFlow(DirectedGraph directedGraph, V source, V sink, + Function edgeCapacityTransformer, Map edgeFlowMap, + Supplier edgeFactory) { + + if(directedGraph.getVertices().contains(source) == false || + directedGraph.getVertices().contains(sink) == false) { + throw new IllegalArgumentException("source and sink vertices must be elements of the specified graph"); + } + if (source.equals(sink)) { + throw new IllegalArgumentException("source and sink vertices must be distinct"); + } + mOriginalGraph = directedGraph; + + this.source = source; + this.target = sink; + this.edgeFlowMap = edgeFlowMap; + this.edgeCapacityTransformer = edgeCapacityTransformer; + this.edgeFactory = edgeFactory; + try { + mFlowGraph = directedGraph.getClass().newInstance(); + for(E e : mOriginalGraph.getEdges()) { + mFlowGraph.addEdge(e, mOriginalGraph.getSource(e), + mOriginalGraph.getDest(e), EdgeType.DIRECTED); + } + for(V v : mOriginalGraph.getVertices()) { + mFlowGraph.addVertex(v); + } + + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + mMaxFlow = 0; + mSinkPartitionNodes = new HashSet(); + mSourcePartitionNodes = new HashSet(); + mMinCutEdges = new HashSet(); + } + + private void clearParentValues() { + parentMap.clear(); + parentCapacityMap.clear(); + parentCapacityMap.put(source, Integer.MAX_VALUE); + parentMap.put(source, source); + } + + protected boolean hasAugmentingPath() { + + mSinkPartitionNodes.clear(); + mSourcePartitionNodes.clear(); + mSinkPartitionNodes.addAll(mFlowGraph.getVertices()); + + Set visitedEdgesMap = new HashSet(); + Queue queue = new LinkedList(); + queue.add(source); + + while (!queue.isEmpty()) { + V currentVertex = queue.remove(); + mSinkPartitionNodes.remove(currentVertex); + mSourcePartitionNodes.add(currentVertex); + Number currentCapacity = parentCapacityMap.get(currentVertex); + + Collection neighboringEdges = mFlowGraph.getOutEdges(currentVertex); + + for (E neighboringEdge : neighboringEdges) { + + V neighboringVertex = mFlowGraph.getDest(neighboringEdge); + + Number residualCapacity = residualCapacityMap.get(neighboringEdge); + if (residualCapacity.intValue() <= 0 || visitedEdgesMap.contains(neighboringEdge)) + continue; + + V neighborsParent = parentMap.get(neighboringVertex); + Number neighborCapacity = parentCapacityMap.get(neighboringVertex); + int newCapacity = Math.min(residualCapacity.intValue(),currentCapacity.intValue()); + + if ((neighborsParent == null) || newCapacity > neighborCapacity.intValue()) { + parentMap.put(neighboringVertex, currentVertex); + parentCapacityMap.put(neighboringVertex, new Integer(newCapacity)); + visitedEdgesMap.add(neighboringEdge); + if (neighboringVertex != target) { + queue.add(neighboringVertex); + } + } + } + } + + boolean hasAugmentingPath = false; + Number targetsParentCapacity = parentCapacityMap.get(target); + if (targetsParentCapacity != null && targetsParentCapacity.intValue() > 0) { + updateResidualCapacities(); + hasAugmentingPath = true; + } + clearParentValues(); + return hasAugmentingPath; + } + + @Override + public void step() { + while (hasAugmentingPath()) { + } + computeMinCut(); +// return 0; + } + + private void computeMinCut() { + + for (E e : mOriginalGraph.getEdges()) { + + V source = mOriginalGraph.getSource(e); + V destination = mOriginalGraph.getDest(e); + if (mSinkPartitionNodes.contains(source) && mSinkPartitionNodes.contains(destination)) { + continue; + } + if (mSourcePartitionNodes.contains(source) && mSourcePartitionNodes.contains(destination)) { + continue; + } + if (mSinkPartitionNodes.contains(source) && mSourcePartitionNodes.contains(destination)) { + continue; + } + mMinCutEdges.add(e); + } + } + + /** + * @return the value of the maximum flow from the source to the sink. + */ + public int getMaxFlow() { + return mMaxFlow; + } + + /** + * @return the nodes which share the same partition (as defined by the min-cut edges) + * as the sink node. + */ + public Set getNodesInSinkPartition() { + return mSinkPartitionNodes; + } + + /** + * @return the nodes which share the same partition (as defined by the min-cut edges) + * as the source node. + */ + public Set getNodesInSourcePartition() { + return mSourcePartitionNodes; + } + + /** + * @return the edges in the minimum cut. + */ + public Set getMinCutEdges() { + return mMinCutEdges; + } + + /** + * @return the graph for which the maximum flow is calculated. + */ + public DirectedGraph getFlowGraph() { + return mFlowGraph; + } + + @Override + protected void initializeIterations() { + parentCapacityMap.put(source, Integer.MAX_VALUE); + parentMap.put(source, source); + + List edgeList = new ArrayList(mFlowGraph.getEdges()); + + for (int eIdx=0;eIdx< edgeList.size();eIdx++) { + E edge = edgeList.get(eIdx); + Number capacity = edgeCapacityTransformer.apply(edge); + + if (capacity == null) { + throw new IllegalArgumentException("Edge capacities must be provided in Function passed to constructor"); + } + residualCapacityMap.put(edge, capacity); + + V source = mFlowGraph.getSource(edge); + V destination = mFlowGraph.getDest(edge); + + if(mFlowGraph.isPredecessor(source, destination) == false) { + E backEdge = edgeFactory.get(); + mFlowGraph.addEdge(backEdge, destination, source, EdgeType.DIRECTED); + residualCapacityMap.put(backEdge, 0); + } + } + } + + @Override + protected void finalizeIterations() { + + for (E currentEdge : mFlowGraph.getEdges()) { + Number capacity = edgeCapacityTransformer.apply(currentEdge); + + Number residualCapacity = residualCapacityMap.get(currentEdge); + if (capacity != null) { + Integer flowValue = new Integer(capacity.intValue()-residualCapacity.intValue()); + this.edgeFlowMap.put(currentEdge, flowValue); + } + } + + Set backEdges = new HashSet(); + for (E currentEdge: mFlowGraph.getEdges()) { + + if (edgeCapacityTransformer.apply(currentEdge) == null) { + backEdges.add(currentEdge); + } else { + residualCapacityMap.remove(currentEdge); + } + } + for(E e : backEdges) { + mFlowGraph.removeEdge(e); + } + } + + private void updateResidualCapacities() { + + Number augmentingPathCapacity = parentCapacityMap.get(target); + mMaxFlow += augmentingPathCapacity.intValue(); + V currentVertex = target; + V parentVertex = null; + while ((parentVertex = parentMap.get(currentVertex)) != currentVertex) { + E currentEdge = mFlowGraph.findEdge(parentVertex, currentVertex); + + Number residualCapacity = residualCapacityMap.get(currentEdge); + + residualCapacity = residualCapacity.intValue() - augmentingPathCapacity.intValue(); + residualCapacityMap.put(currentEdge, residualCapacity); + + E backEdge = mFlowGraph.findEdge(currentVertex, parentVertex); + residualCapacity = residualCapacityMap.get(backEdge); + residualCapacity = residualCapacity.intValue() + augmentingPathCapacity.intValue(); + residualCapacityMap.put(backEdge, residualCapacity); + currentVertex = parentVertex; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/flows/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +Methods for calculating properties relating to network flows (such as max flow/min cut). + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/EvolvingGraphGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.generators; + + + +/** + * An interface for algorithms that generate graphs that evolve iteratively. + * @author Scott White + */ +public interface EvolvingGraphGenerator extends GraphGenerator { + + /** + * Instructs the algorithm to evolve the graph N steps. + * @param numSteps number of steps to iterate from the current state + */ + void evolveGraph(int numSteps); + + /** + * Retrieves the total number of steps elapsed. + * @return number of elapsed steps + */ + int numIterations(); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/GraphGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.generators; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; + +/** + * An interface for algorithms that generate graphs. + * @author Scott White + */ +public interface GraphGenerator extends Supplier>{ } + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/Lattice2DGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2009, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.algorithms.generators; + +import java.util.ArrayList; +import java.util.List; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * Simple generator of an m x n lattice where each vertex + * is incident with each of its neighbors (to the left, right, up, and down). + * May be toroidal, in which case the vertices on the edges are connected to + * their counterparts on the opposite edges as well. + * + *

If the graph Supplier supplied has a default edge type of {@code EdgeType.DIRECTED}, + * then edges will be created in both directions between adjacent vertices. + * + * @author Joshua O'Madadhain + */ +public class Lattice2DGenerator implements GraphGenerator +{ + protected int row_count; + protected int col_count; + protected boolean is_toroidal; + protected boolean is_directed; + protected Supplier> graph_factory; + protected Supplier vertex_factory; + protected Supplier edge_factory; + private List v_array; + + /** + * Constructs a generator of square lattices of size {@code latticeSize} + * with the specified parameters. + * + * @param graph_factory used to create the {@code Graph} for the lattice + * @param vertex_factory used to create the lattice vertices + * @param edge_factory used to create the lattice edges + * @param latticeSize the number of rows and columns of the lattice + * @param isToroidal if true, the created lattice wraps from top to bottom and left to right + */ + public Lattice2DGenerator(Supplier> graph_factory, Supplier vertex_factory, + Supplier edge_factory, int latticeSize, boolean isToroidal) + { + this(graph_factory, vertex_factory, edge_factory, latticeSize, latticeSize, isToroidal); + } + + /** + * Creates a generator of {@code row_count} x {@code col_count} lattices + * with the specified parameters. + * + * @param graph_factory used to create the {@code Graph} for the lattice + * @param vertex_factory used to create the lattice vertices + * @param edge_factory used to create the lattice edges + * @param row_count the number of rows in the lattice + * @param col_count the number of columns in the lattice + * @param isToroidal if true, the created lattice wraps from top to bottom and left to right + */ + public Lattice2DGenerator(Supplier> graph_factory, Supplier vertex_factory, + Supplier edge_factory, int row_count, int col_count, boolean isToroidal) + { + if (row_count < 2 || col_count < 2) + { + throw new IllegalArgumentException("Row and column counts must each be at least 2."); + } + + this.row_count = row_count; + this.col_count = col_count; + this.is_toroidal = isToroidal; + this.graph_factory = graph_factory; + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + this.is_directed = (graph_factory.get().getDefaultEdgeType() == EdgeType.DIRECTED); + } + + /** + * Generates a graph based on the constructor-specified settings. + * + * @return the generated graph + */ + public Graph get() + { + int vertex_count = row_count * col_count; + Graph graph = graph_factory.get(); + v_array = new ArrayList(vertex_count); + for (int i = 0; i < vertex_count; i++) + { + V v = vertex_factory.get(); + graph.addVertex(v); + v_array.add(i, v); + } + + int start = is_toroidal ? 0 : 1; + int end_row = is_toroidal ? row_count : row_count - 1; + int end_col = is_toroidal ? col_count : col_count - 1; + + // fill in edges + // down + for (int i = 0; i < end_row; i++) + for (int j = 0; j < col_count; j++) + graph.addEdge(edge_factory.get(), getVertex(i,j), getVertex(i+1, j)); + // right + for (int i = 0; i < row_count; i++) + for (int j = 0; j < end_col; j++) + graph.addEdge(edge_factory.get(), getVertex(i,j), getVertex(i, j+1)); + + // if the graph is directed, fill in the edges going the other direction... + if (graph.getDefaultEdgeType() == EdgeType.DIRECTED) + { + // up + for (int i = start; i < row_count; i++) + for (int j = 0; j < col_count; j++) + graph.addEdge(edge_factory.get(), getVertex(i,j), getVertex(i-1, j)); + // left + for (int i = 0; i < row_count; i++) + for (int j = start; j < col_count; j++) + graph.addEdge(edge_factory.get(), getVertex(i,j), getVertex(i, j-1)); + } + + return graph; + } + + /** + * Returns the number of edges found in a lattice of this generator's specifications. + * (This is useful for subclasses that may modify the generated graphs to add more edges.) + * + * @return the number of edges that this generator will generate + */ + public int getGridEdgeCount() + { + int boundary_adjustment = (is_toroidal ? 0 : 1); + int vertical_edge_count = col_count * (row_count - boundary_adjustment); + int horizontal_edge_count = row_count * (col_count - boundary_adjustment); + + return (vertical_edge_count + horizontal_edge_count) * (is_directed ? 2 : 1); + } + + protected int getIndex(int i, int j) + { + return ((mod(i, row_count)) * col_count) + (mod(j, col_count)); + } + + protected int mod(int i, int modulus) + { + int i_mod = i % modulus; + return i_mod >= 0 ? i_mod : i_mod + modulus; + } + + /** + * @param i row index into the lattice + * @param j column index into the lattice + * @return the vertex at position ({@code i mod row_count, j mod col_count}) + */ + protected V getVertex(int i, int j) + { + return v_array.get(getIndex(i, j)); + } + + /** + * @param i row index into the lattice + * @return the {@code i}th vertex (counting row-wise) + */ + protected V getVertex(int i) + { + return v_array.get(i); + } + + /** + * @param i index of the vertex whose row we want + * @return the row in which the vertex with index {@code i} is found + */ + protected int getRow(int i) + { + return i / col_count; + } + + /** + * @param i index of the vertex whose column we want + * @return the column in which the vertex with index {@code i} is found + */ + protected int getCol(int i) + { + return i % col_count; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +Methods for generating new (often random) graphs with various properties. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/BarabasiAlbertGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.EvolvingGraphGenerator; +import edu.uci.ics.jung.algorithms.util.WeightedChoice; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.MultiGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + *

+ * Simple evolving scale-free random graph generator. At each time step, a new + * vertex is created and is connected to existing vertices according to the + * principle of "preferential attachment", whereby vertices with higher degree + * have a higher probability of being selected for attachment. + * + *

+ * At a given timestep, the probability p of creating an edge + * between an existing vertex v and the newly added vertex is + * + *

+ * p = (degree(v) + 1) / (|E| + |V|);
+ * 
+ * + *

+ * where |E| and |V| are, respectively, the number of + * edges and vertices currently in the network (counting neither the new vertex + * nor the other edges that are being attached to it). + * + *

+ * Note that the formula specified in the original paper (cited below) was + * + *

+ * p = degree(v) / |E|
+ * 
+ * + * + *

+ * However, this would have meant that the probability of attachment for any + * existing isolated vertex would be 0. This version uses Lagrangian smoothing + * to give each existing vertex a positive attachment probability. + * + *

+ * The graph created may be either directed or undirected (controlled by a + * constructor parameter); the default is undirected. If the graph is specified + * to be directed, then the edges added will be directed from the newly added + * vertex u to the existing vertex v, with probability proportional to the + * indegree of v (number of edges directed towards v). If the graph is specified + * to be undirected, then the (undirected) edges added will connect u to v, with + * probability proportional to the degree of v. + * + *

+ * The parallel constructor parameter specifies whether parallel + * edges may be created. + * + * @see "A.-L. Barabasi and R. Albert, Emergence of scaling in random networks, Science 286, 1999." + * @author Scott White + * @author Joshua O'Madadhain + * @author Tom Nelson - adapted to jung2 + * @author James Marchant + */ +public class BarabasiAlbertGenerator implements EvolvingGraphGenerator { + private Graph mGraph = null; + private int mNumEdgesToAttachPerStep; + private int mElapsedTimeSteps; + private Random mRandom; + protected List vertex_index; + protected int init_vertices; + protected Map index_vertex; + protected Supplier> graphFactory; + protected Supplier vertexFactory; + protected Supplier edgeFactory; + + /** + * Constructs a new instance of the generator. + * + * @param graphFactory + * factory for graphs of the appropriate type + * @param vertexFactory + * factory for vertices of the appropriate type + * @param edgeFactory + * factory for edges of the appropriate type + * @param init_vertices + * number of unconnected 'seed' vertices that the graph should + * start with + * @param numEdgesToAttach + * the number of edges that should be attached from the new + * vertex to pre-existing vertices at each time step + * @param seed + * random number seed + * @param seedVertices + * storage for the seed vertices that this graph creates + */ + // TODO: seedVertices is a bizarre way of exposing that information, + // refactor + public BarabasiAlbertGenerator(Supplier> graphFactory, Supplier vertexFactory, + Supplier edgeFactory, int init_vertices, int numEdgesToAttach, int seed, Set seedVertices) { + Preconditions.checkArgument(init_vertices > 0, + "Number of initial unconnected 'seed' vertices must be positive"); + Preconditions.checkArgument(numEdgesToAttach > 0, + "Number of edges to attach at each time step must be positive"); + Preconditions.checkArgument(numEdgesToAttach <= init_vertices, + "Number of edges to attach at each time step must less than or equal to the number of initial vertices"); + + mNumEdgesToAttachPerStep = numEdgesToAttach; + mRandom = new Random(seed); + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + this.init_vertices = init_vertices; + initialize(seedVertices); + } + + /** + * Constructs a new instance of the generator, whose output will be an + * undirected graph, and which will use the current time as a seed for the + * random number generation. + * + * @param graphFactory + * factory for graphs of the appropriate type + * @param vertexFactory + * factory for vertices of the appropriate type + * @param edgeFactory + * factory for edges of the appropriate type + * @param init_vertices + * number of vertices that the graph should start with + * @param numEdgesToAttach + * the number of edges that should be attached from the new + * vertex to pre-existing vertices at each time step + * @param seedVertices + * storage for the seed vertices that this graph creates + */ + public BarabasiAlbertGenerator(Supplier> graphFactory, Supplier vertexFactory, + Supplier edgeFactory, int init_vertices, int numEdgesToAttach, Set seedVertices) { + this(graphFactory, vertexFactory, edgeFactory, init_vertices, numEdgesToAttach, + (int) System.currentTimeMillis(), seedVertices); + } + + private void initialize(Set seedVertices) { + mGraph = graphFactory.get(); + + vertex_index = new ArrayList(2 * init_vertices); + index_vertex = new HashMap(2 * init_vertices); + for (int i = 0; i < init_vertices; i++) { + V v = vertexFactory.get(); + mGraph.addVertex(v); + vertex_index.add(v); + index_vertex.put(v, i); + seedVertices.add(v); + } + + mElapsedTimeSteps = 0; + } + + public void evolveGraph(int numTimeSteps) { + + for (int i = 0; i < numTimeSteps; i++) { + evolveGraph(); + mElapsedTimeSteps++; + } + } + + private void evolveGraph() { + Collection preexistingNodes = mGraph.getVertices(); + V newVertex = vertexFactory.get(); + + mGraph.addVertex(newVertex); + + // generate and store the new edges; don't add them to the graph + // yet because we don't want to bias the degree calculations + // (all new edges in a timestep should be added in parallel) + Set> added_pairs = createRandomEdges(preexistingNodes, newVertex, mNumEdgesToAttachPerStep); + + for (Pair pair : added_pairs) { + V v1 = pair.getFirst(); + V v2 = pair.getSecond(); + if (mGraph.getDefaultEdgeType() != EdgeType.UNDIRECTED || !mGraph.isNeighbor(v1, v2)) + mGraph.addEdge(edgeFactory.get(), pair); + } + // now that we're done attaching edges to this new vertex, + // add it to the index + vertex_index.add(newVertex); + index_vertex.put(newVertex, new Integer(vertex_index.size() - 1)); + } + + private Set> createRandomEdges(Collection preexistingNodes, V newVertex, int numEdges) { + Set> added_pairs = new HashSet>(numEdges * 3); + + /* Generate the probability distribution */ + Map item_weights = new HashMap(); + for (V v : preexistingNodes) { + /* + * as preexistingNodes is a view onto the vertex set, it will + * contain the new node. In the construction of Barabasi-Albert, + * there should be no self-loops. + */ + if (v == newVertex) + continue; + + double degree; + double denominator; + + /* + * Attachment probability is dependent on whether the graph is + * directed or undirected. + * + * Subtract 1 from numVertices because we don't want to count + * newVertex (which has already been added to the graph, but not to + * vertex_index). + */ + if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED) { + degree = mGraph.degree(v); + denominator = (2 * mGraph.getEdgeCount()) + mGraph.getVertexCount() - 1; + } else { + degree = mGraph.inDegree(v); + denominator = mGraph.getEdgeCount() + mGraph.getVertexCount() - 1; + } + + double prob = (degree + 1) / denominator; + item_weights.put(v, prob); + } + WeightedChoice nodeProbabilities = new WeightedChoice(item_weights, mRandom); + + for (int i = 0; i < numEdges; i++) { + createRandomEdge(preexistingNodes, newVertex, added_pairs, nodeProbabilities); + } + + return added_pairs; + } + + private void createRandomEdge(Collection preexistingNodes, V newVertex, Set> added_pairs, + WeightedChoice weightedProbabilities) { + V attach_point; + boolean created_edge = false; + Pair endpoints; + + do { + attach_point = weightedProbabilities.nextItem(); + + endpoints = new Pair(newVertex, attach_point); + + /* + * If parallel edges are not allowed, skip attach_point if + * already exists; note that because of + * the way the new node's edges are added, we only need to check the + * list of candidate edges for duplicates. + */ + if (!(mGraph instanceof MultiGraph)) { + if (added_pairs.contains(endpoints)) + continue; + if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED + && added_pairs.contains(new Pair(attach_point, newVertex))) + continue; + } + created_edge = true; + } while (!created_edge); + + added_pairs.add(endpoints); + + if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED) { + added_pairs.add(new Pair(attach_point, newVertex)); + } + } + + public int numIterations() { + return mElapsedTimeSteps; + } + + public Graph get() { + return mGraph; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/EppsteinPowerLawGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,128 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.GraphGenerator; +import edu.uci.ics.jung.graph.Graph; + +/** + * Graph generator that generates undirected graphs with power-law degree distributions. + * @author Scott White + * @see "A Steady State Model for Graph Power Law by David Eppstein and Joseph Wang" + */ +public class EppsteinPowerLawGenerator implements GraphGenerator { + private int mNumVertices; + private int mNumEdges; + private int mNumIterations; + private double mMaxDegree; + private Random mRandom; + private Supplier> graphFactory; + private Supplier vertexFactory; + private Supplier edgeFactory; + + /** + * Creates an instance with the specified factories and specifications. + * @param graphFactory the Supplier to use to generate the graph + * @param vertexFactory the Supplier to use to create vertices + * @param edgeFactory the Supplier to use to create edges + * @param numVertices the number of vertices for the generated graph + * @param numEdges the number of edges the generated graph will have, should be Theta(numVertices) + * @param r the number of iterations to use; the larger the value the better the graph's degree + * distribution will approximate a power-law + */ + public EppsteinPowerLawGenerator(Supplier> graphFactory, + Supplier vertexFactory, Supplier edgeFactory, + int numVertices, int numEdges, int r) { + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mNumVertices = numVertices; + mNumEdges = numEdges; + mNumIterations = r; + mRandom = new Random(); + } + + protected Graph initializeGraph() { + Graph graph = null; + graph = graphFactory.get(); + for(int i=0; i vertices = new ArrayList(graph.getVertices()); + while (graph.getEdgeCount() < mNumEdges) { + V u = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + V v = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + if (!graph.isSuccessor(v,u)) { + graph.addEdge(edgeFactory.get(), u, v); + } + } + + double maxDegree = 0; + for (V v : graph.getVertices()) { + maxDegree = Math.max(graph.degree(v),maxDegree); + } + mMaxDegree = maxDegree; //(maxDegree+1)*(maxDegree)/2; + + return graph; + } + + /** + * Generates a graph whose degree distribution approximates a power-law. + * @return the generated graph + */ + public Graph get() { + Graph graph = initializeGraph(); + + List vertices = new ArrayList(graph.getVertices()); + for (int rIdx = 0; rIdx < mNumIterations; rIdx++) { + + V v = null; + int degree = 0; + do { + v = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + degree = graph.degree(v); + + } while (degree == 0); + + List edges = new ArrayList(graph.getIncidentEdges(v)); + E randomExistingEdge = edges.get((int) (mRandom.nextDouble()*degree)); + + // FIXME: look at email thread on a more efficient RNG for arbitrary distributions + + V x = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + V y = null; + do { + y = vertices.get((int) (mRandom.nextDouble() * mNumVertices)); + + } while (mRandom.nextDouble() > ((graph.degree(y)+1)/mMaxDegree)); + + if (!graph.isSuccessor(y,x) && x != y) { + graph.removeEdge(randomExistingEdge); + graph.addEdge(edgeFactory.get(), x, y); + } + } + + return graph; + } + + /** + * Sets the seed for the random number generator. + * @param seed input to the random number generator. + */ + public void setSeed(long seed) { + mRandom.setSeed(seed); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/ErdosRenyiGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,105 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.GraphGenerator; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Generates a random graph using the Erdos-Renyi binomial model + * (each pair of vertices is connected with probability p). + * + * @author William Giordano, Scott White, Joshua O'Madadhain + */ +public class ErdosRenyiGenerator implements GraphGenerator { + private int mNumVertices; + private double mEdgeConnectionProbability; + private Random mRandom; + Supplier> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + + /** + * + * @param graphFactory factory for graphs of the appropriate type + * @param vertexFactory factory for vertices of the appropriate type + * @param edgeFactory factory for edges of the appropriate type + * @param numVertices number of vertices graph should have + * @param p Connection's probability between 2 vertices + */ + public ErdosRenyiGenerator(Supplier> graphFactory, + Supplier vertexFactory, Supplier edgeFactory, + int numVertices,double p) + { + if (numVertices <= 0) { + throw new IllegalArgumentException("A positive # of vertices must be specified."); + } + mNumVertices = numVertices; + if (p < 0 || p > 1) { + throw new IllegalArgumentException("p must be between 0 and 1."); + } + this.graphFactory = graphFactory; + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mEdgeConnectionProbability = p; + mRandom = new Random(); + } + + /** + * Returns a graph in which each pair of vertices is connected by + * an undirected edge with the probability specified by the constructor. + */ + public Graph get() { + UndirectedGraph g = graphFactory.get(); + for(int i=0; i list = new ArrayList(g.getVertices()); + + for (int i = 0; i < mNumVertices-1; i++) { + V v_i = list.get(i); + for (int j = i+1; j < mNumVertices; j++) { + V v_j = list.get(j); + if (mRandom.nextDouble() < mEdgeConnectionProbability) { + g.addEdge(edgeFactory.get(), v_i, v_j); + } + } + } + return g; + } + + /** + * Sets the seed of the internal random number generator to {@code seed}. + * Enables consistent behavior. + * + * @param seed the seed to use for the internal random number generator + */ + public void setSeed(long seed) { + mRandom.setSeed(seed); + } +} + + + + + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/KleinbergSmallWorldGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,192 @@ + +package edu.uci.ics.jung.algorithms.generators.random; + +/* +* Copyright (c) 2009, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.Lattice2DGenerator; +import edu.uci.ics.jung.algorithms.util.WeightedChoice; +import edu.uci.ics.jung.graph.Graph; + +/** + * Graph generator that produces a random graph with small world properties. + * The underlying model is an mxn (optionally toroidal) lattice. Each node u + * has four local connections, one to each of its neighbors, and + * in addition 1+ long range connections to some node v where v is chosen randomly according to + * probability proportional to d^-alpha where d is the lattice distance between u and v and alpha + * is the clustering exponent. + * + * @see "Navigation in a small world J. Kleinberg, Nature 406(2000), 845." + * @author Joshua O'Madadhain + */ +public class KleinbergSmallWorldGenerator extends Lattice2DGenerator { + private double clustering_exponent; + private Random random; + private int num_connections = 1; + + /** + * Creates an instance with the specified parameters, whose underlying lattice is (a) of size + * {@code latticeSize} x {@code latticeSize}, and (b) toroidal. + * @param graphFactory factory for graphs of the appropriate type + * @param vertexFactory factory for vertices of the appropriate type + * @param edgeFactory factory for edges of the appropriate type + * @param latticeSize the number of rows and columns of the underlying lattice + * @param clusteringExponent the clustering exponent + */ + public KleinbergSmallWorldGenerator(Supplier> graphFactory, + Supplier vertexFactory, Supplier edgeFactory, + int latticeSize, double clusteringExponent) + { + this(graphFactory, vertexFactory, edgeFactory, latticeSize, latticeSize, clusteringExponent); + } + + /** + * Creates an instance with the specified parameters, whose underlying lattice is toroidal. + * @param graphFactory factory for graphs of the appropriate type + * @param vertexFactory factory for vertices of the appropriate type + * @param edgeFactory factory for edges of the appropriate type + * @param row_count number of rows of the underlying lattice + * @param col_count number of columns of the underlying lattice + * @param clusteringExponent the clustering exponent + */ + public KleinbergSmallWorldGenerator(Supplier> graphFactory, + Supplier vertexFactory, Supplier edgeFactory, + int row_count, int col_count, double clusteringExponent) + { + super(graphFactory, vertexFactory, edgeFactory, row_count, col_count, true); + clustering_exponent = clusteringExponent; + initialize(); + } + + /** + * Creates an instance with the specified parameters. + * @param graphFactory factory for graphs of the appropriate type + * @param vertexFactory factory for vertices of the appropriate type + * @param edgeFactory factory for edges of the appropriate type + * @param row_count number of rows of the underlying lattice + * @param col_count number of columns of the underlying lattice + * @param clusteringExponent the clustering exponent + * @param isToroidal whether the underlying lattice is toroidal + */ + public KleinbergSmallWorldGenerator(Supplier> graphFactory, + Supplier vertexFactory, Supplier edgeFactory, + int row_count, int col_count, double clusteringExponent, boolean isToroidal) + { + super(graphFactory, vertexFactory, edgeFactory, row_count, col_count, isToroidal); + clustering_exponent = clusteringExponent; + initialize(); + } + + private void initialize() + { + this.random = new Random(); + } + + /** + * Sets the {@code Random} instance used by this instance. Useful for + * unit testing. + * @param random the {@code Random} instance for this class to use + */ + public void setRandom(Random random) + { + this.random = random; + } + + /** + * Sets the seed of the internal random number generator. May be used to provide repeatable + * experiments. + * @param seed the random seed that this class's random number generator is to use + */ + public void setRandomSeed(long seed) + { + random.setSeed(seed); + } + + /** + * Sets the number of new 'small-world' connections (outgoing edges) to be added to each vertex. + * @param num_connections the number of outgoing small-world edges to add to each vertex + */ + public void setConnectionCount(int num_connections) + { + if (num_connections <= 0) + { + throw new IllegalArgumentException("Number of new connections per vertex must be >= 1"); + } + this.num_connections = num_connections; + } + + /** + * @return the number of new 'small-world' connections that will originate at each vertex + */ + public int getConnectionCount() + { + return this.num_connections; + } + + /** + * Generates a random small world network according to the parameters given + * @return a random small world graph + */ + @Override + public Graph get() + { + Graph graph = super.get(); + + // TODO: For toroidal graphs, we can make this more clever by pre-creating the WeightedChoice object + // and using the output as an offset to the current vertex location. + WeightedChoice weighted_choice; + + // Add long range connections + for (int i = 0; i < graph.getVertexCount(); i++) + { + V source = getVertex(i); + int row = getRow(i); + int col = getCol(i); + int row_offset = row < row_count/2 ? -row_count : row_count; + int col_offset = col < col_count/2 ? -col_count : col_count; + + Map vertex_weights = new HashMap(); + for (int j = 0; j < row_count; j++) + { + for (int k = 0; k < col_count; k++) + { + if (j == row && k == col) + continue; + int v_dist = Math.abs(j - row); + int h_dist = Math.abs(k - col); + if (is_toroidal) + { + v_dist = Math.min(v_dist, Math.abs(j - row+row_offset)); + h_dist = Math.min(h_dist, Math.abs(k - col+col_offset)); + } + int distance = v_dist + h_dist; + if (distance < 2) + continue; + else + vertex_weights.put(getVertex(j,k), (float)Math.pow(distance, -clustering_exponent)); + } + } + + for (int j = 0; j < this.num_connections; j++) { + weighted_choice = new WeightedChoice(vertex_weights, random); + V target = weighted_choice.nextItem(); + graph.addEdge(edge_factory.get(), source, target); + } + } + + return graph; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/MixedRandomGraphGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Jul 2, 2003 + * + */ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * Generates a mixed-mode random graph (with random edge weights) based on the output of + * BarabasiAlbertGenerator. + * Primarily intended for providing a heterogeneous sample graph for visualization testing, etc. + */ +public class MixedRandomGraphGenerator { + + /** + * Returns a random mixed-mode graph. Starts with a randomly generated + * Barabasi-Albert (preferential attachment) generator + * (4 initial vertices, 3 edges added at each step, and num_vertices - 4 evolution steps). + * Then takes the resultant graph, replaces random undirected edges with directed + * edges, and assigns random weights to each edge. + * @param the vertex type + * @param the edge type + * @param graphFactory factory for graphs of the appropriate type + * @param vertexFactory factory for vertices of the appropriate type + * @param edgeFactory factory for edges of the appropriate type + * @param edge_weights storage for the edge weights that this generator creates + * @param num_vertices number of vertices to generate + * @param seedVertices storage for the seed vertices that this generator creates + * @return the generated graph + */ + public static Graph generateMixedRandomGraph( + Supplier> graphFactory, + Supplier vertexFactory, + Supplier edgeFactory, + Map edge_weights, + int num_vertices, Set seedVertices) + { + int seed = (int)(Math.random() * 10000); + BarabasiAlbertGenerator bag = + new BarabasiAlbertGenerator(graphFactory, vertexFactory, edgeFactory, + 4, 3, //false, parallel, + seed, seedVertices); + bag.evolveGraph(num_vertices - 4); + Graph ug = bag.get(); + + Graph g = graphFactory.get(); + for(V v : ug.getVertices()) { + g.addVertex(v); + } + + // randomly replace some of the edges by directed edges to + // get a mixed-mode graph, add random weights + + for(E e : ug.getEdges()) { + V v1 = ug.getEndpoints(e).getFirst(); + V v2 = ug.getEndpoints(e).getSecond(); + + E me = edgeFactory.get(); + g.addEdge(me, v1, v2, Math.random() < .5 ? EdgeType.DIRECTED : EdgeType.UNDIRECTED); + edge_weights.put(me, Math.random()); + } + + return g; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/generators/random/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,27 @@ + + + + + + + +Methods for generating random graphs with various properties. These include: +

    +
  • BarabasiAlbertGenerator: scale-free graphs using the preferential attachment heuristic. +
  • EppsteinPowerLawGenerator: graphs whose degree distribution approximates a power law +
  • ErdosRenyiGenerator: graphs for which edges are created with a specified probability +
  • MixedRandomGraphGenerator: takes the output of BarabasiAlbertGenerator and +perturbs it to generate a mixed-mode analog with both directed and undirected edges. +
  • + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/AbstractRanker.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,392 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.text.DecimalFormat; +import java.text.Format; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.util.IterativeProcess; +import edu.uci.ics.jung.graph.Graph; + +/** + * Abstract class for algorithms that rank nodes or edges by some "importance" metric. Provides a common set of + * services such as: + *
      + *
    • storing rank scores
    • + *
    • getters and setters for rank scores
    • + *
    • computing default edge weights
    • + *
    • normalizing default or user-provided edge transition weights
    • + *
    • normalizing rank scores
    • + *
    • automatic cleanup of decorations
    • + *
    • creation of Ranking list
    • + *
    • print rankings in sorted order by rank
    • + *
    + *

    + * By default, all rank scores are removed from the vertices (or edges) being ranked. + * @author Scott White + */ +public abstract class AbstractRanker extends IterativeProcess { + private Graph mGraph; + private List> mRankings; + private boolean mRemoveRankScoresOnFinalize; + private boolean mRankNodes; + private boolean mRankEdges; + private boolean mNormalizeRankings; + protected LoadingCache> vertexRankScores + = CacheBuilder.newBuilder().build(new CacheLoader>() { + public Map load(Object o) { + return new HashMap(); + } + }); + protected LoadingCache> edgeRankScores + = CacheBuilder.newBuilder().build(new CacheLoader>() { + public Map load(Object o) { + return new HashMap(); + } + }); + + private Map edgeWeights = new HashMap(); + + protected void initialize(Graph graph, boolean isNodeRanker, + boolean isEdgeRanker) { + if (!isNodeRanker && !isEdgeRanker) + throw new IllegalArgumentException("Must rank edges, vertices, or both"); + mGraph = graph; + mRemoveRankScoresOnFinalize = true; + mNormalizeRankings = true; + mRankNodes = isNodeRanker; + mRankEdges = isEdgeRanker; + } + + /** + * @return all rankScores + */ + public Map> getVertexRankScores() { + return vertexRankScores.asMap(); + } + + public Map> getEdgeRankScores() { + return edgeRankScores.asMap(); + } + + /** + * @param key the rank score key whose scores are to be retrieved + * @return the rank scores for the specified key + */ + public Map getVertexRankScores(Object key) { + return vertexRankScores.getUnchecked(key); + } + + public Map getEdgeRankScores(Object key) { + return edgeRankScores.getUnchecked(key); + } + + protected Collection getVertices() { + return mGraph.getVertices(); + } + + protected int getVertexCount() { + return mGraph.getVertexCount(); + } + + protected Graph getGraph() { + return mGraph; + } + + @Override + public void reset() { + } + + /** + * @return true if this ranker ranks nodes, and + * false otherwise. + */ + public boolean isRankingNodes() { + return mRankNodes; + } + + /** + * @return true if this ranker ranks edges, and + * false otherwise. + */ + public boolean isRankingEdges() { + return mRankEdges; + } + + /** + * Instructs the ranker whether or not it should remove the rank scores from the nodes (or edges) once the ranks + * have been computed. + * @param removeRankScoresOnFinalize true if the rank scores are to be removed, false otherwise + */ + public void setRemoveRankScoresOnFinalize(boolean removeRankScoresOnFinalize) { + this.mRemoveRankScoresOnFinalize = removeRankScoresOnFinalize; + } + + protected void onFinalize(Object e) {} + + /** + * The user datum key used to store the rank score. + * @return the key + */ + abstract public Object getRankScoreKey(); + + + @SuppressWarnings("unchecked") + @Override + protected void finalizeIterations() { + List> sortedRankings = new ArrayList>(); + + int id = 1; + if (mRankNodes) { + for (V currentVertex : getVertices()) { + Ranking ranking = new Ranking(id,getVertexRankScore(currentVertex),currentVertex); + sortedRankings.add(ranking); + if (mRemoveRankScoresOnFinalize) { + this.vertexRankScores.getUnchecked(getRankScoreKey()).remove(currentVertex); + } + id++; + onFinalize(currentVertex); + } + } + if (mRankEdges) { + for (E currentEdge : mGraph.getEdges()) { + + Ranking ranking = new Ranking(id,getEdgeRankScore(currentEdge),currentEdge); + sortedRankings.add(ranking); + if (mRemoveRankScoresOnFinalize) { + this.edgeRankScores.getUnchecked(getRankScoreKey()).remove(currentEdge); + } + id++; + onFinalize(currentEdge); + } + } + + mRankings = sortedRankings; + Collections.sort(mRankings); + } + + /** + * Retrieves the list of ranking instances in descending sorted order by rank score + * If the algorithm is ranking edges, the instances will be of type EdgeRanking, otherwise + * if the algorithm is ranking nodes the instances will be of type NodeRanking + * @return the list of rankings + */ + public List> getRankings() { + return mRankings; + } + + /** + * Return a list of the top k rank scores. + * @param topKRankings the value of k to use + * @return list of rank scores + */ + public List getRankScores(int topKRankings) { + List scores = new ArrayList(); + int count=1; + for (Ranking currentRanking : getRankings()) { + if (count > topKRankings) { + return scores; + } + scores.add(currentRanking.rankScore); + count++; + } + + return scores; + } + + /** + * Given a node, returns the corresponding rank score. This is a default + * implementation of getRankScore which assumes the decorations are of type MutableDouble. + * This method only returns legal values if setRemoveRankScoresOnFinalize(false) was called + * prior to evaluate(). + * + * @param v the node whose rank score is to be returned. + * @return the rank score value + */ + public double getVertexRankScore(V v) { + Number rankScore = vertexRankScores.getUnchecked(getRankScoreKey()).get(v); + if (rankScore != null) { + return rankScore.doubleValue(); + } else { + throw new RuntimeException("setRemoveRankScoresOnFinalize(false) must be called before evaluate()."); + } + } + + public double getVertexRankScore(V v, Object key) { + return vertexRankScores.getUnchecked(key).get(v).doubleValue(); + } + + public double getEdgeRankScore(E e) { + Number rankScore = edgeRankScores.getUnchecked(getRankScoreKey()).get(e); + if (rankScore != null) { + return rankScore.doubleValue(); + } else { + throw new RuntimeException("setRemoveRankScoresOnFinalize(false) must be called before evaluate()."); + } + } + + public double getEdgeRankScore(E e, Object key) { + return edgeRankScores.getUnchecked(key).get(e).doubleValue(); + } + + protected void setVertexRankScore(V v, double rankValue, Object key) { + vertexRankScores.getUnchecked(key).put(v, rankValue); + } + + protected void setEdgeRankScore(E e, double rankValue, Object key) { + edgeRankScores.getUnchecked(key).put(e, rankValue); + } + + protected void setVertexRankScore(V v, double rankValue) { + setVertexRankScore(v,rankValue, getRankScoreKey()); + } + + protected void setEdgeRankScore(E e, double rankValue) { + setEdgeRankScore(e, rankValue, getRankScoreKey()); + } + + protected void removeVertexRankScore(V v, Object key) { + vertexRankScores.getUnchecked(key).remove(v); + } + + protected void removeEdgeRankScore(E e, Object key) { + edgeRankScores.getUnchecked(key).remove(e); + } + + protected void removeVertexRankScore(V v) { + vertexRankScores.getUnchecked(getRankScoreKey()).remove(v); + } + + protected void removeEdgeRankScore(E e) { + edgeRankScores.getUnchecked(getRankScoreKey()).remove(e); + } + + protected double getEdgeWeight(E e) { + return edgeWeights.get(e).doubleValue(); + } + + protected void setEdgeWeight(E e, double weight) { + edgeWeights.put(e, weight); + } + + public void setEdgeWeights(Map edgeWeights) { + this.edgeWeights = edgeWeights; + } + + /** + * @return the edgeWeights + */ + public Map getEdgeWeights() { + return edgeWeights; + } + + protected void assignDefaultEdgeTransitionWeights() { + + for (V currentVertex : getVertices()) { + + Collection outgoingEdges = mGraph.getOutEdges(currentVertex); + + double numOutEdges = outgoingEdges.size(); + for (E currentEdge : outgoingEdges) { + setEdgeWeight(currentEdge,1.0/numOutEdges); + } + } + } + + protected void normalizeEdgeTransitionWeights() { + + for (V currentVertex : getVertices()) { + + Collection outgoingEdges = mGraph.getOutEdges(currentVertex); + + double totalEdgeWeight = 0; + for (E currentEdge : outgoingEdges) { + totalEdgeWeight += getEdgeWeight(currentEdge); + } + + for (E currentEdge : outgoingEdges) { + setEdgeWeight(currentEdge,getEdgeWeight(currentEdge)/totalEdgeWeight); + } + } + } + + protected void normalizeRankings() { + if (!mNormalizeRankings) { + return; + } + double totalWeight = 0; + + for (V currentVertex : getVertices()) { + totalWeight += getVertexRankScore(currentVertex); + } + + for (V currentVertex : getVertices()) { + setVertexRankScore(currentVertex,getVertexRankScore(currentVertex)/totalWeight); + } + } + + /** + * Print the rankings to standard out in descending order of rank score + * @param verbose if true, include information about the actual rank order as well as + * the original position of the vertex before it was ranked + * @param printScore if true, include the actual value of the rank score + */ + public void printRankings(boolean verbose,boolean printScore) { + double total = 0; + Format formatter = new DecimalFormat("#0.#######"); + int rank = 1; + + for (Ranking currentRanking : getRankings()) { + double rankScore = currentRanking.rankScore; + if (verbose) { + System.out.print("Rank " + rank + ": "); + if (printScore) { + System.out.print(formatter.format(rankScore)); + } + System.out.print("\tVertex Id: " + currentRanking.originalPos); + System.out.print(" (" + currentRanking.getRanked() + ")"); + System.out.println(); + } else { + System.out.print(rank + "\t"); + if (printScore) { + System.out.print(formatter.format(rankScore)); + } + System.out.println("\t" + currentRanking.originalPos); + + } + total += rankScore; + rank++; + } + + if (verbose) { + System.out.println("Total: " + formatter.format(total)); + } + } + + /** + * Allows the user to specify whether or not s/he wants the rankings to be normalized. + * In some cases, this will have no effect since the algorithm doesn't allow normalization + * as an option + * @param normalizeRankings {@code true} iff the ranking are to be normalized + */ + public void setNormalizeRankings(boolean normalizeRankings) { + mNormalizeRankings = normalizeRankings; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/BetweennessCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,189 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Stack; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Computes betweenness centrality for each vertex and edge in the graph. The result is that each vertex + * and edge has a UserData element of type MutableDouble whose key is 'centrality.BetweennessCentrality'. + * Note: Many social network researchers like to normalize the betweenness values by dividing the values by + * (n-1)(n-2)/2. The values given here are unnormalized.

    + * + * A simple example of usage is: + *

    + * BetweennessCentrality ranker = new BetweennessCentrality(someGraph);
    + * ranker.evaluate();
    + * ranker.printRankings();
    + * 
    + * + * Running time is: O(n^2 + nm). + * @see "Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25(2):163-177, 2001." + * @author Scott White + * @author Tom Nelson converted to jung2 + */ + +public class BetweennessCentrality extends AbstractRanker { + + public static final String CENTRALITY = "centrality.BetweennessCentrality"; + + /** + * Constructor which initializes the algorithm + * @param g the graph whose nodes are to be analyzed + */ + public BetweennessCentrality(Graph g) { + initialize(g, true, true); + } + + public BetweennessCentrality(Graph g, boolean rankNodes) { + initialize(g, rankNodes, true); + } + + public BetweennessCentrality(Graph g, boolean rankNodes, boolean rankEdges) + { + initialize(g, rankNodes, rankEdges); + } + + protected void computeBetweenness(Graph graph) { + + Map decorator = new HashMap(); + Map bcVertexDecorator = + vertexRankScores.getUnchecked(getRankScoreKey()); + bcVertexDecorator.clear(); + Map bcEdgeDecorator = + edgeRankScores.getUnchecked(getRankScoreKey()); + bcEdgeDecorator.clear(); + + Collection vertices = graph.getVertices(); + + for (V s : vertices) { + + initializeData(graph,decorator); + + decorator.get(s).numSPs = 1; + decorator.get(s).distance = 0; + + Stack stack = new Stack(); + Queue queue = new LinkedList(); + queue.add(s); + + while (!queue.isEmpty()) { + V v = queue.remove(); + stack.push(v); + + for(V w : getGraph().getSuccessors(v)) { + + if (decorator.get(w).distance < 0) { + queue.add(w); + decorator.get(w).distance = decorator.get(v).distance + 1; + } + + if (decorator.get(w).distance == decorator.get(v).distance + 1) { + decorator.get(w).numSPs += decorator.get(v).numSPs; + decorator.get(w).predecessors.add(v); + } + } + } + + while (!stack.isEmpty()) { + V w = stack.pop(); + + for (V v : decorator.get(w).predecessors) { + + double partialDependency = (decorator.get(v).numSPs / decorator.get(w).numSPs); + partialDependency *= (1.0 + decorator.get(w).dependency); + decorator.get(v).dependency += partialDependency; + E currentEdge = getGraph().findEdge(v, w); + double edgeValue = bcEdgeDecorator.get(currentEdge).doubleValue(); + edgeValue += partialDependency; + bcEdgeDecorator.put(currentEdge, edgeValue); + } + if (w != s) { + double bcValue = bcVertexDecorator.get(w).doubleValue(); + bcValue += decorator.get(w).dependency; + bcVertexDecorator.put(w, bcValue); + } + } + } + + if(graph instanceof UndirectedGraph) { + for (V v : vertices) { + double bcValue = bcVertexDecorator.get(v).doubleValue(); + bcValue /= 2.0; + bcVertexDecorator.put(v, bcValue); + } + for (E e : graph.getEdges()) { + double bcValue = bcEdgeDecorator.get(e).doubleValue(); + bcValue /= 2.0; + bcEdgeDecorator.put(e, bcValue); + } + } + + for (V vertex : vertices) { + decorator.remove(vertex); + } + } + + private void initializeData(Graph g, Map decorator) { + for (V vertex : g.getVertices()) { + + Map bcVertexDecorator = vertexRankScores.getUnchecked(getRankScoreKey()); + if(bcVertexDecorator.containsKey(vertex) == false) { + bcVertexDecorator.put(vertex, 0.0); + } + decorator.put(vertex, new BetweennessData()); + } + for (E e : g.getEdges()) { + + Map bcEdgeDecorator = edgeRankScores.getUnchecked(getRankScoreKey()); + if(bcEdgeDecorator.containsKey(e) == false) { + bcEdgeDecorator.put(e, 0.0); + } + } + } + + /** + * the user datum key used to store the rank scores + * @return the key + */ + @Override + public String getRankScoreKey() { + return CENTRALITY; + } + + @Override + public void step() { + computeBetweenness(getGraph()); + } + + class BetweennessData { + double distance; + double numSPs; + List predecessors; + double dependency; + + BetweennessData() { + distance = -1; + numSPs = 0; + predecessors = new ArrayList(); + dependency = 0; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/KStepMarkov.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,135 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import edu.uci.ics.jung.graph.DirectedGraph; + + +/** + * Algorithm variant of PageRankWithPriors that computes the importance of a node based upon taking fixed-length random + * walks out from the root set and then computing the stationary probability of being at each node. Specifically, it computes + * the relative probability that the markov chain will spend at any particular node, given that it start in the root + * set and ends after k steps. + *

    + * A simple example of usage is: + *

    + * KStepMarkov ranker = new KStepMarkov(someGraph,rootSet,6,null);
    + * ranker.evaluate();
    + * ranker.printRankings();
    + * 
    + *

    + * + * @author Scott White + * @author Tom Nelson - adapter to jung2 + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class KStepMarkov extends RelativeAuthorityRanker { + public final static String RANK_SCORE = "jung.algorithms.importance.KStepMarkovExperimental.RankScore"; + private final static String CURRENT_RANK = "jung.algorithms.importance.KStepMarkovExperimental.CurrentRank"; + private int mNumSteps; + HashMap mPreviousRankingsMap; + + /** + * Construct the algorihm instance and initializes the algorithm. + * @param graph the graph to be analyzed + * @param priors the set of root nodes + * @param k positive integer parameter which controls the relative tradeoff between a distribution "biased" towards + * R and the steady-state distribution which is independent of where the Markov-process started. Generally values + * between 4-8 are reasonable + * @param edgeWeights the weight for each edge + */ + public KStepMarkov(DirectedGraph graph, Set priors, int k, Map edgeWeights) { + super.initialize(graph,true,false); + mNumSteps = k; + setPriors(priors); + initializeRankings(); + if (edgeWeights == null) { + assignDefaultEdgeTransitionWeights(); + } else { + setEdgeWeights(edgeWeights); + } + normalizeEdgeTransitionWeights(); + } + + /** + * The user datum key used to store the rank scores. + * @return the key + */ + @Override + public String getRankScoreKey() { + return RANK_SCORE; + } + + protected void incrementRankScore(V v, double rankValue) { + double value = getVertexRankScore(v, RANK_SCORE); + value += rankValue; + setVertexRankScore(v, value, RANK_SCORE); + } + + protected double getCurrentRankScore(V v) { + return getVertexRankScore(v, CURRENT_RANK); + } + + protected void setCurrentRankScore(V v, double rankValue) { + setVertexRankScore(v, rankValue, CURRENT_RANK); + } + + protected void initializeRankings() { + mPreviousRankingsMap = new HashMap(); + for (V v : getVertices()) { + Set priors = getPriors(); + double numPriors = priors.size(); + + if (getPriors().contains(v)) { + setVertexRankScore(v, 1.0/ numPriors); + setCurrentRankScore(v, 1.0/ numPriors); + mPreviousRankingsMap.put(v,1.0/numPriors); + } else { + setVertexRankScore(v, 0); + setCurrentRankScore(v, 0); + mPreviousRankingsMap.put(v, 0); + } + } + } + @Override + public void step() { + + for (int i=0;i incomingEdges = getGraph().getInEdges(v); + + double currentPageRankSum = 0; + for (E e : incomingEdges) { + double currentWeight = getEdgeWeight(e); + currentPageRankSum += + mPreviousRankingsMap.get(getGraph().getOpposite(v,e)).doubleValue()*currentWeight; + } + setCurrentRankScore(v,currentPageRankSum); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/Ranking.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,79 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + + +/** + * Abstract data container for ranking objects. Stores common data relevant to both node and edge rankings, namely, + * the original position of the instance in the list and the actual ranking score. + * @author Scott White + */ +@SuppressWarnings("rawtypes") +public class Ranking implements Comparable { + /** + * The original (0-indexed) position of the instance being ranked + */ + public int originalPos; + /** + * The actual rank score (normally between 0 and 1) + */ + public double rankScore; + + /** + * what is being ranked + */ + private V ranked; + + /** + * Constructor which allows values to be set on construction + * @param originalPos The original (0-indexed) position of the instance being ranked + * @param rankScore The actual rank score (normally between 0 and 1) + * @param ranked the vertex being ranked + */ + public Ranking(int originalPos, double rankScore, V ranked) { + this.originalPos = originalPos; + this.rankScore = rankScore; + this.ranked = ranked; + } + + /** + * Compares two ranking based on the rank score. + * @param other The other ranking + * @return -1 if the other ranking is higher, 0 if they are equal, and 1 if this ranking is higher + */ + public int compareTo(Object other) { + @SuppressWarnings("unchecked") + Ranking otherRanking = (Ranking) other; + return Double.compare(otherRanking.rankScore,rankScore); + } + + /** + * Returns the rank score as a string. + * @return the stringified rank score + */ + @Override + public String toString() { + return String.valueOf(rankScore); + } + + /** + * @return the ranked element + */ + public V getRanked() { + return ranked; + } + + /** + * @param ranked the ranked to set + */ + public void setRanked(V ranked) { + this.ranked = ranked; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/RelativeAuthorityRanker.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + + +/** + * This class provides basic infrastructure for relative authority algorithms that compute the importance of nodes + * relative to one or more root nodes. The services provided are: + *

      + *
    • The set of root nodes (priors) is stored and maintained
    • + *
    • Getters and setters for the prior rank score are provided
    • + *
    + * + * @author Scott White + */ +public abstract class RelativeAuthorityRanker extends AbstractRanker { + private Set mPriors; + /** + * The default key used for the user datum key corresponding to prior rank scores. + */ + + protected Map priorRankScoreMap = new HashMap(); + /** + * Cleans up all of the prior rank scores on finalize. + */ + @Override + protected void finalizeIterations() { + super.finalizeIterations(); + priorRankScoreMap.clear(); + } + + /** + * Retrieves the value of the prior rank score. + * @param v the root node (prior) + * @return the prior rank score + */ + protected double getPriorRankScore(V v) { + return priorRankScoreMap.get(v).doubleValue(); + + } + + /** + * Allows the user to specify a value to set for the prior rank score + * @param v the root node (prior) + * @param value the score to set to + */ + public void setPriorRankScore(V v, double value) { + this.priorRankScoreMap.put(v, value); + } + + /** + * Retrieves the set of priors. + * @return the set of root nodes (priors) + */ + protected Set getPriors() { return mPriors; } + + /** + * Specifies which vertices are root nodes (priors). + * @param priors the root nodes + */ + protected void setPriors(Set priors) { mPriors = priors; } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/importance/WeightedNIPaths.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,196 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; + + + +/** + * This algorithm measures the importance of nodes based upon both the number and length of disjoint paths that lead + * to a given node from each of the nodes in the root set. Specifically the formula for measuring the importance of a + * node is given by: I(t|R) = sum_i=1_|P(r,t)|_{alpha^|p_i|} where alpha is the path decay coefficient, p_i is path i + * and P(r,t) is a set of maximum-sized node-disjoint paths from r to t. + *

    + * This algorithm uses heuristic breadth-first search to try and find the maximum-sized set of node-disjoint paths + * between two nodes. As such, it is not guaranteed to give exact answers. + *

    + * A simple example of usage is: + *

    + * WeightedNIPaths ranker = new WeightedNIPaths(someGraph,2.0,6,rootSet);
    + * ranker.evaluate();
    + * ranker.printRankings();
    + * 
    + * + * @author Scott White + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class WeightedNIPaths extends AbstractRanker { + public final static String WEIGHTED_NIPATHS_KEY = "jung.algorithms.importance.WEIGHTED_NIPATHS_KEY"; + private double mAlpha; + private int mMaxDepth; + private Set mPriors; + private Map pathIndices = new HashMap(); + private Map roots = new HashMap(); + private Map> pathsSeenMap = new HashMap>(); + private Supplier vertexFactory; + private Supplier edgeFactory; + + /** + * Constructs and initializes the algorithm. + * @param graph the graph whose nodes are being measured for their importance + * @param vertexFactory used to generate instances of V + * @param edgeFactory used to generate instances of E + * @param alpha the path decay coefficient (≥1); 2 is recommended + * @param maxDepth the maximal depth to search out from the root set + * @param priors the root set (starting vertices) + */ + public WeightedNIPaths(DirectedGraph graph, Supplier vertexFactory, + Supplier edgeFactory, double alpha, int maxDepth, Set priors) { + super.initialize(graph, true,false); + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + mAlpha = alpha; + mMaxDepth = maxDepth; + mPriors = priors; + for (V v : graph.getVertices()) { + super.setVertexRankScore(v, 0.0); + } + } + + protected void incrementRankScore(V v, double rankValue) { + setVertexRankScore(v, getVertexRankScore(v) + rankValue); + } + + protected void computeWeightedPathsFromSource(V root, int depth) { + + int pathIdx = 1; + + for (E e : getGraph().getOutEdges(root)) { + this.pathIndices.put(e, pathIdx); + this.roots.put(e, root); + newVertexEncountered(pathIdx, getGraph().getEndpoints(e).getSecond(), root); + pathIdx++; + } + + List edges = new ArrayList(); + + V virtualNode = vertexFactory.get(); + getGraph().addVertex(virtualNode); + E virtualSinkEdge = edgeFactory.get(); + + getGraph().addEdge(virtualSinkEdge, virtualNode, root); + edges.add(virtualSinkEdge); + + int currentDepth = 0; + while (currentDepth <= depth) { + + double currentWeight = Math.pow(mAlpha, -1.0 * currentDepth); + for (E currentEdge : edges) { + incrementRankScore(getGraph().getEndpoints(currentEdge).getSecond(),// + currentWeight); + } + + if ((currentDepth == depth) || (edges.size() == 0)) break; + + List newEdges = new ArrayList(); + + for (E currentSourceEdge : edges) { //Iterator sourceEdgeIt = edges.iterator(); sourceEdgeIt.hasNext();) { + Number sourcePathIndex = this.pathIndices.get(currentSourceEdge); + + // from the currentSourceEdge, get its opposite end + // then iterate over the out edges of that opposite end + V newDestVertex = getGraph().getEndpoints(currentSourceEdge).getSecond(); + Collection outs = getGraph().getOutEdges(newDestVertex); + for (E currentDestEdge : outs) { + V destEdgeRoot = this.roots.get(currentDestEdge); + V destEdgeDest = getGraph().getEndpoints(currentDestEdge).getSecond(); + + if (currentSourceEdge == virtualSinkEdge) { + newEdges.add(currentDestEdge); + continue; + } + if (destEdgeRoot == root) { + continue; + } + if (destEdgeDest == getGraph().getEndpoints(currentSourceEdge).getFirst()) {//currentSourceEdge.getSource()) { + continue; + } + Set pathsSeen = this.pathsSeenMap.get(destEdgeDest); + + if (pathsSeen == null) { + newVertexEncountered(sourcePathIndex.intValue(), destEdgeDest, root); + } else if (roots.get(destEdgeDest) != root) { + roots.put(destEdgeDest,root); + pathsSeen.clear(); + pathsSeen.add(sourcePathIndex); + } else if (!pathsSeen.contains(sourcePathIndex)) { + pathsSeen.add(sourcePathIndex); + } else { + continue; + } + + this.pathIndices.put(currentDestEdge, sourcePathIndex); + this.roots.put(currentDestEdge, root); + newEdges.add(currentDestEdge); + } + } + + edges = newEdges; + currentDepth++; + } + + getGraph().removeVertex(virtualNode); + } + + private void newVertexEncountered(int sourcePathIndex, V dest, V root) { + Set pathsSeen = new HashSet(); + pathsSeen.add(sourcePathIndex); + this.pathsSeenMap.put(dest, pathsSeen); + roots.put(dest, root); + } + + @Override + public void step() { + for (V v : mPriors) { + computeWeightedPathsFromSource(v, mMaxDepth); + } + + normalizeRankings(); +// return 0; + } + + /** + * Given a node, returns the corresponding rank score. This implementation of getRankScore assumes + * the decoration representing the rank score is of type MutableDouble. + * @return the rank score for this node + */ + @Override + public String getRankScoreKey() { + return WEIGHTED_NIPATHS_KEY; + } + + @Override + protected void onFinalize(Object udc) { + pathIndices.remove(udc); + roots.remove(udc); + pathsSeenMap.remove(udc); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AbstractLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 7, 2003 + * + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Preconditions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Abstract class for implementations of {@code Layout}. It handles some of the + * basic functions: storing coordinates, maintaining the dimensions, initializing + * the locations, maintaining locked vertices. + * + * @author Danyel Fisher, Scott White + * @author Tom Nelson - converted to jung2 + * @param the vertex type + * @param the edge type + */ +abstract public class AbstractLayout implements Layout { + + /** + * A set of vertices that are fixed in place and not affected by the layout algorithm + */ + private Set dontmove = new HashSet(); + + protected Dimension size; + protected Graph graph; + protected boolean initialized; + + protected LoadingCache locations = + CacheBuilder.newBuilder().build(new CacheLoader() { + public Point2D load(V vertex) { + return new Point2D.Double(); + } + }); + + /** + * Creates an instance for {@code graph} which does not initialize the vertex locations. + * + * @param graph the graph on which the layout algorithm is to operate + */ + protected AbstractLayout(Graph graph) { + if (graph == null) + { + throw new IllegalArgumentException("Graph must be non-null"); + } + this.graph = graph; + } + + /** + * Creates an instance for {@code graph} which initializes the vertex locations + * using {@code initializer}. + * + * @param graph the graph on which the layout algorithm is to operate + * @param initializer specifies the starting positions of the vertices + */ + protected AbstractLayout(Graph graph, Function initializer) { + this.graph = graph; + Function chain = + Functions.compose( + new Function(){ + public Point2D apply(Point2D p) { + return (Point2D)p.clone(); + }}, + initializer + ); + this.locations = CacheBuilder.newBuilder().build(CacheLoader.from(chain)); + initialized = true; + } + + /** + * Creates an instance for {@code graph} which sets the size of the layout to {@code size}. + * + * @param graph the graph on which the layout algorithm is to operate + * @param size the dimensions of the region in which the layout algorithm will place vertices + */ + protected AbstractLayout(Graph graph, Dimension size) { + this.graph = graph; + this.size = size; + } + + /** + * Creates an instance for {@code graph} which initializes the vertex locations + * using {@code initializer} and sets the size of the layout to {@code size}. + * + * @param graph the graph on which the layout algorithm is to operate + * @param initializer specifies the starting positions of the vertices + * @param size the dimensions of the region in which the layout algorithm will place vertices + */ + protected AbstractLayout(Graph graph, Function initializer, Dimension size) { + this.graph = graph; + Function chain = + Functions.compose( + new Function(){ + public Point2D apply(Point2D p) { + return (Point2D)p.clone(); + }}, + initializer + ); + this.locations = CacheBuilder.newBuilder().build(CacheLoader.from(chain)); + this.size = size; + } + + public void setGraph(Graph graph) { + this.graph = graph; + if(size != null && graph != null) { + initialize(); + } + } + + /** + * When a visualization is resized, it presumably wants to fix the + * locations of the vertices and possibly to reinitialize its data. The + * current method calls initializeLocations followed by initialize_local. + */ + public void setSize(Dimension size) { + + if(size != null && graph != null) { + + Dimension oldSize = this.size; + this.size = size; + initialize(); + + if(oldSize != null) { + adjustLocations(oldSize, size); + } + } + } + + private void adjustLocations(Dimension oldSize, Dimension size) { + + int xOffset = (size.width - oldSize.width) / 2; + int yOffset = (size.height - oldSize.height) / 2; + + // now, move each vertex to be at the new screen center + while(true) { + try { + for(V v : getGraph().getVertices()) { + offsetVertex(v, xOffset, yOffset); + } + break; + } catch(ConcurrentModificationException cme) { + } + } + } + + public boolean isLocked(V v) { + return dontmove.contains(v); + } + + public void setInitializer(Function initializer) { + if(this.equals(initializer)) { + throw new IllegalArgumentException("Layout cannot be initialized with itself"); + } + Function chain = + Functions.compose( + new Function(){ + public Point2D apply(Point2D p) { + return (Point2D)p.clone(); + }}, + initializer + ); + this.locations = CacheBuilder.newBuilder().build(CacheLoader.from(chain)); + initialized = true; + } + + /** + * Returns the current size of the visualization space, accoring to the + * last call to resize(). + * + * @return the current size of the screen + */ + public Dimension getSize() { + return size; + } + + /** + * Returns the Coordinates object that stores the vertex' x and y location. + * + * @param v + * A Vertex that is a part of the Graph being visualized. + * @return A Coordinates object with x and y locations. + */ + private Point2D getCoordinates(V v) { + return locations.getUnchecked(v); + } + + public Point2D apply(V v) { + return getCoordinates(v); + } + + /** + * Returns the x coordinate of the vertex from the Coordinates object. + * in most cases you will be better off calling transform(v). + * + * @param v the vertex whose x coordinate is to be returned + * @return the x coordinate of {@code v} + */ + public double getX(V v) { + Preconditions.checkNotNull(getCoordinates(v), "Cannot getX for an unmapped vertex "+v); + return getCoordinates(v).getX(); + } + + /** + * Returns the y coordinate of the vertex from the Coordinates object. + * In most cases you will be better off calling transform(v). + * + * @param v the vertex whose y coordinate is to be returned + * @return the y coordinate of {@code v} + */ + public double getY(V v) { + Preconditions.checkNotNull(getCoordinates(v), "Cannot getY for an unmapped vertex "+v); + return getCoordinates(v).getY(); + } + + /** + * @param v the vertex whose coordinates are to be offset + * @param xOffset the change to apply to this vertex's x coordinate + * @param yOffset the change to apply to this vertex's y coordinate + */ + protected void offsetVertex(V v, double xOffset, double yOffset) { + Point2D c = getCoordinates(v); + c.setLocation(c.getX()+xOffset, c.getY()+yOffset); + setLocation(v, c); + } + + /** + * @return the graph that this layout operates on + */ + public Graph getGraph() { + return graph; + } + + /** + * Forcibly moves a vertex to the (x,y) location by setting its x and y + * locations to the specified location. Does not add the vertex to the + * "dontmove" list, and (in the default implementation) does not make any + * adjustments to the rest of the graph. + * @param picked the vertex whose location is being set + * @param x the x coordinate of the location to set + * @param y the y coordinate of the location to set + */ + public void setLocation(V picked, double x, double y) { + Point2D coord = getCoordinates(picked); + coord.setLocation(x, y); + } + + public void setLocation(V picked, Point2D p) { + Point2D coord = getCoordinates(picked); + coord.setLocation(p); + } + + /** + * Locks {@code v} in place if {@code state} is {@code true}, otherwise unlocks it. + * @param v the vertex whose position is to be (un)locked + * @param state {@code true} if the vertex is to be locked, {@code false} if to be unlocked + */ + public void lock(V v, boolean state) { + if(state == true) + dontmove.add(v); + else + dontmove.remove(v); + } + + /** + * @param lock {@code true} to lock all vertices in place, {@code false} to unlock all vertices + */ + public void lock(boolean lock) { + for(V v : graph.getVertices()) { + lock(v, lock); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/AggregateLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * A {@code Layout} implementation that combines + * multiple other layouts so that they may be manipulated + * as one layout. The relaxer thread will step each layout + * in sequence. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class AggregateLayout implements Layout, IterativeContext { + + protected Layout delegate; + protected Map,Point2D> layouts = new HashMap,Point2D>(); + + /** + * Creates an instance backed by the specified {@code delegate}. + * @param delegate the layout to which this instance is delegating + */ + public AggregateLayout(Layout delegate) { + this.delegate = delegate; + } + + /** + * @return the delegate + */ + public Layout getDelegate() { + return delegate; + } + + /** + * @param delegate the delegate to set + */ + public void setDelegate(Layout delegate) { + this.delegate = delegate; + } + + /** + * Adds the passed layout as a sublayout, and specifies + * the center of where this sublayout should appear. + * @param layout the layout algorithm to use as a sublayout + * @param center the center of the coordinates for the sublayout + */ + public void put(Layout layout, Point2D center) { + layouts.put(layout,center); + } + + /** + * @param layout the layout whose center is to be returned + * @return the center of the passed layout + */ + public Point2D get(Layout layout) { + return layouts.get(layout); + } + + /** + * Removes {@code layout} from this instance. + * @param layout the layout to remove + */ + public void remove(Layout layout) { + layouts.remove(layout); + } + + /** + * Removes all layouts from this instance. + */ + public void removeAll() { + layouts.clear(); + } + + public Graph getGraph() { + return delegate.getGraph(); + } + + public Dimension getSize() { + return delegate.getSize(); + } + + public void initialize() { + delegate.initialize(); + for(Layout layout : layouts.keySet()) { + layout.initialize(); + } + } + + /** + * @param v the vertex whose locked state is to be returned + * @return true if v is locked in any of the layouts, and false otherwise + */ + public boolean isLocked(V v) { + for(Layout layout : layouts.keySet()) { + if (layout.isLocked(v)) { + return true; + } + } + return delegate.isLocked(v); + } + + /** + * Locks this vertex in the main layout and in any sublayouts whose graph contains + * this vertex. + * @param v the vertex whose locked state is to be set + * @param state {@code true} if the vertex is to be locked, and {@code false} if unlocked + */ + public void lock(V v, boolean state) { + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + layout.lock(v, state); + } + } + delegate.lock(v, state); + } + + public void reset() { + for(Layout layout : layouts.keySet()) { + layout.reset(); + } + delegate.reset(); + } + + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } + + public void setInitializer(Function initializer) { + delegate.setInitializer(initializer); + } + + public void setLocation(V v, Point2D location) { + boolean wasInSublayout = false; + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + Point2D center = layouts.get(layout); + // transform by the layout itself, but offset to the + // center of the sublayout + Dimension d = layout.getSize(); + + AffineTransform at = + AffineTransform.getTranslateInstance(-center.getX()+d.width/2,-center.getY()+d.height/2); + Point2D localLocation = at.transform(location, null); + layout.setLocation(v, localLocation); + wasInSublayout = true; + } + } + if(wasInSublayout == false && getGraph().getVertices().contains(v)) { + delegate.setLocation(v, location); + } + } + + public void setSize(Dimension d) { + delegate.setSize(d); + } + + /** + * @return a map from each {@code Layout} instance to its center point. + */ + public Map,Point2D> getLayouts() { + return layouts; + } + + /** + * Returns the location of the vertex. The location is specified first + * by the sublayouts, and then by the base layout if no sublayouts operate + * on this vertex. + * @return the location of the vertex + */ + public Point2D apply(V v) { + boolean wasInSublayout = false; + for(Layout layout : layouts.keySet()) { + if(layout.getGraph().getVertices().contains(v)) { + wasInSublayout = true; + Point2D center = layouts.get(layout); + // transform by the layout itself, but offset to the + // center of the sublayout + Dimension d = layout.getSize(); + AffineTransform at = + AffineTransform.getTranslateInstance(center.getX()-d.width/2, + center.getY()-d.height/2); + return at.transform(layout.apply(v),null); + } + } + if(wasInSublayout == false) { + return delegate.apply(v); + } + return null; + + } + + /** + * @return {@code true} iff the delegate layout and all sublayouts are done + */ + public boolean done() { + for (Layout layout : layouts.keySet()) { + if (layout instanceof IterativeContext) { + if (! ((IterativeContext) layout).done() ) { + return false; + } + } + } + if(delegate instanceof IterativeContext) { + return ((IterativeContext)delegate).done(); + } + return true; + } + + /** + * Call step on any sublayout that is also an IterativeContext and is not done + */ + public void step() { + for(Layout layout : layouts.keySet()) { + if(layout instanceof IterativeContext) { + IterativeContext context = (IterativeContext)layout; + if(context.done() == false) { + context.step(); + } + } + } + if(delegate instanceof IterativeContext) { + IterativeContext context = (IterativeContext)delegate; + if(context.done() == false) { + context.step(); + } + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/BalloonLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * A {@code Layout} implementation that assigns positions to {@code Tree} or + * {@code Forest} vertices using associations with nested circles ("balloons"). + * A balloon is nested inside another balloon if the first balloon's subtree + * is a subtree of the second balloon's subtree. + * + * @author Tom Nelson + * + */ +public class BalloonLayout extends TreeLayout { + + protected LoadingCache polarLocations + = CacheBuilder.newBuilder().build(new CacheLoader() { + public PolarPoint load(V vertex) { + return new PolarPoint(); + } + }); + + protected Map radii = new HashMap(); + + /** + * Creates an instance based on the input forest. + * @param g the forest on which this layout will operate + */ + public BalloonLayout(Forest g) + { + super(g); + } + + protected void setRootPolars() + { + List roots = TreeUtils.getRoots(graph); + if(roots.size() == 1) { + // its a Tree + V root = roots.get(0); + setRootPolar(root); + setPolars(new ArrayList(graph.getChildren(root)), + getCenter(), getSize().width/2); + } else if (roots.size() > 1) { + // its a Forest + setPolars(roots, getCenter(), getSize().width/2); + } + } + + protected void setRootPolar(V root) { + PolarPoint pp = new PolarPoint(0,0); + Point2D p = getCenter(); + polarLocations.put(root, pp); + locations.put(root, p); + } + + + protected void setPolars(List kids, Point2D parentLocation, double parentRadius) { + + int childCount = kids.size(); + if(childCount == 0) return; + // handle the 1-child case with 0 limit on angle. + double angle = Math.max(0, Math.PI / 2 * (1 - 2.0/childCount)); + double childRadius = parentRadius*Math.cos(angle) / (1 + Math.cos(angle)); + double radius = parentRadius - childRadius; + + double rand = Math.random(); + + for(int i=0; i< childCount; i++) { + V child = kids.get(i); + double theta = i* 2*Math.PI/childCount + rand; + radii.put(child, childRadius); + + PolarPoint pp = new PolarPoint(theta, radius); + polarLocations.put(child, pp); + + Point2D p = PolarPoint.polarToCartesian(pp); + p.setLocation(p.getX()+parentLocation.getX(), p.getY()+parentLocation.getY()); + locations.put(child, p); + setPolars(new ArrayList(graph.getChildren(child)), p, childRadius); + } + } + + @Override + public void setSize(Dimension size) { + this.size = size; + setRootPolars(); + } + + /** + * @param v the vertex whose center is to be returned + * @return the coordinates of {@code v}'s parent, or the center of this layout's area if it's a root. + */ + public Point2D getCenter(V v) { + V parent = graph.getParent(v); + if(parent == null) { + return getCenter(); + } + return locations.getUnchecked(parent); + } + + @Override + public void setLocation(V v, Point2D location) { + Point2D c = getCenter(v); + Point2D pv = new Point2D.Double(location.getX()-c.getX(),location.getY()-c.getY()); + PolarPoint newLocation = PolarPoint.cartesianToPolar(pv); + polarLocations.getUnchecked(v).setLocation(newLocation); + + Point2D center = getCenter(v); + pv.setLocation(pv.getX()+center.getX(), pv.getY()+center.getY()); + locations.put(v, pv); + } + + @Override + public Point2D apply(V v) { + return locations.getUnchecked(v); + } + + /** + * @return the radii + */ + public Map getRadii() { + return radii; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/CircleLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Dec 4, 2003 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.graph.Graph; + + + +/** + * A {@code Layout} implementation that positions vertices equally spaced on a regular circle. + * + * @author Masanori Harada + */ +public class CircleLayout extends AbstractLayout { + + private double radius; + private List vertex_ordered_list; + + protected LoadingCache circleVertexDatas = + CacheBuilder.newBuilder().build(new CacheLoader() { + public CircleVertexData load(V vertex) { + return new CircleVertexData(); + } + }); + + public CircleLayout(Graph g) { + super(g); + } + + /** + * @return the radius of the circle. + */ + public double getRadius() { + return radius; + } + + /** + * Sets the radius of the circle. Must be called before {@code initialize()} is called. + * @param radius the radius of the circle + */ + public void setRadius(double radius) { + this.radius = radius; + } + + /** + * Sets the order of the vertices in the layout according to the ordering + * specified by {@code comparator}. + * @param comparator the comparator to use to order the vertices + */ + public void setVertexOrder(Comparator comparator) + { + if (vertex_ordered_list == null) + vertex_ordered_list = new ArrayList(getGraph().getVertices()); + Collections.sort(vertex_ordered_list, comparator); + } + + /** + * Sets the order of the vertices in the layout according to the ordering + * of {@code vertex_list}. + * @param vertex_list a list specifying the ordering of the vertices + */ + public void setVertexOrder(List vertex_list) + { + if (!vertex_list.containsAll(getGraph().getVertices())) + throw new IllegalArgumentException("Supplied list must include " + + "all vertices of the graph"); + this.vertex_ordered_list = vertex_list; + } + + public void reset() { + initialize(); + } + + public void initialize() + { + Dimension d = getSize(); + + if (d != null) + { + if (vertex_ordered_list == null) + setVertexOrder(new ArrayList(getGraph().getVertices())); + + double height = d.getHeight(); + double width = d.getWidth(); + + if (radius <= 0) { + radius = 0.45 * (height < width ? height : width); + } + + int i = 0; + for (V v : vertex_ordered_list) + { + Point2D coord = apply(v); + + double angle = (2 * Math.PI * i) / vertex_ordered_list.size(); + + coord.setLocation(Math.cos(angle) * radius + width / 2, + Math.sin(angle) * radius + height / 2); + + CircleVertexData data = getCircleData(v); + data.setAngle(angle); + i++; + } + } + } + + protected CircleVertexData getCircleData(V v) { + return circleVertexDatas.getUnchecked(v); + } + + protected static class CircleVertexData { + private double angle; + + protected double getAngle() { + return angle; + } + + protected void setAngle(double angle) { + this.angle = angle; + } + + @Override + public String toString() { + return "CircleVertexData: angle=" + angle; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/DAGLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Dec 4, 2003 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of {@code Layout} suitable for tree-like directed + * acyclic graphs. Parts of it will probably not terminate if the graph is + * cyclic! The layout will result in directed edges pointing generally upwards. + * Any vertices with no successors are considered to be level 0, and tend + * towards the top of the layout. Any vertex has a level one greater than the + * maximum level of all its successors. + * + * + * @author John Yesberg + */ +public class DAGLayout extends SpringLayout { + + /** + * Each vertex has a minimumLevel. Any vertex with no successors has + * minimumLevel of zero. The minimumLevel of any vertex must be strictly + * greater than the minimumLevel of its parents. (Vertex A is a parent of + * Vertex B iff there is an edge from B to A.) Typically, a vertex will + * have a minimumLevel which is one greater than the minimumLevel of its + * parent's. However, if the vertex has two parents, its minimumLevel will + * be one greater than the maximum of the parents'. We need to calculate + * the minimumLevel for each vertex. When we layout the graph, vertices + * cannot be drawn any higher than the minimumLevel. The graphHeight of a + * graph is the greatest minimumLevel that is used. We will modify the + * SpringLayout calculations so that nodes cannot move above their assigned + * minimumLevel. + */ + private Map minLevels = new HashMap(); + // Simpler than the "pair" technique. + static int graphHeight; + static int numRoots; + final double SPACEFACTOR = 1.3; + // How much space do we allow for additional floating at the bottom. + final double LEVELATTRACTIONRATE = 0.8; + + /** + * A bunch of parameters to help work out when to stop quivering. + * + * If the MeanSquareVel(ocity) ever gets below the MSV_THRESHOLD, then we + * will start a final cool-down phase of COOL_DOWN_INCREMENT increments. If + * the MeanSquareVel ever exceeds the threshold, we will exit the cool down + * phase, and continue looking for another opportunity. + */ + final double MSV_THRESHOLD = 10.0; + double meanSquareVel; + boolean stoppingIncrements = false; + int incrementsLeft; + final int COOL_DOWN_INCREMENTS = 200; + + public DAGLayout(Graph g) { + super(g); + } + + /** + * Calculates the level of each vertex in the graph. Level 0 is + * allocated to each vertex with no successors. Level n+1 is allocated to + * any vertex whose successors' maximum level is n. + */ + public void setRoot() { + numRoots = 0; + Graph g = getGraph(); + for(V v : g.getVertices()) { + if (g.getSuccessors(v).isEmpty()) { + setRoot(v); + numRoots++; + } + } + } + + /** + * Set vertex v to be level 0. + * @param v the vertex to set as root + */ + public void setRoot(V v) { + minLevels.put(v, new Integer(0)); + // set all the levels. + propagateMinimumLevel(v); + } + + /** + * A recursive method for allocating the level for each vertex. Ensures + * that all predecessors of v have a level which is at least one greater + * than the level of v. + * + * @param v the vertex whose minimum level is to be calculated + */ + public void propagateMinimumLevel(V v) { + int level = minLevels.get(v).intValue(); + for(V child : getGraph().getPredecessors(v)) { + int oldLevel, newLevel; + Number o = minLevels.get(child); + if (o != null) + oldLevel = o.intValue(); + else + oldLevel = 0; + newLevel = Math.max(oldLevel, level + 1); + minLevels.put(child, new Integer(newLevel)); + + if (newLevel > graphHeight) + graphHeight = newLevel; + propagateMinimumLevel(child); + } + } + + /** + * Sets a random location for a vertex within the dimensions of the space. + * + * @param v the vertex whose position is to be set + * @param coord the coordinates of the vertex once the position has been set + * @param d the dimensions of the space + */ + private void initializeLocation( + V v, + Point2D coord, + Dimension d) { + + int level = minLevels.get(v).intValue(); + int minY = (int) (level * d.getHeight() / (graphHeight * SPACEFACTOR)); + double x = Math.random() * d.getWidth(); + double y = Math.random() * (d.getHeight() - minY) + minY; + coord.setLocation(x,y); + } + + @Override + public void setSize(Dimension size) { + super.setSize(size); + for(V v : getGraph().getVertices()) { + initializeLocation(v,apply(v),getSize()); + } + } + + /** + * Had to override this one as well, to ensure that setRoot() is called. + */ + @Override + public void initialize() { + super.initialize(); + setRoot(); + } + + /** + * Override the moveNodes() method from SpringLayout. The only change we + * need to make is to make sure that nodes don't float higher than the minY + * coordinate, as calculated by their minimumLevel. + */ + @Override + protected void moveNodes() { + // Dimension d = currentSize; + double oldMSV = meanSquareVel; + meanSquareVel = 0; + + synchronized (getSize()) { + + for(V v : getGraph().getVertices()) { + if (isLocked(v)) + continue; + SpringLayout.SpringVertexData vd = springVertexData.getUnchecked(v); + Point2D xyd = apply(v); + + int width = getSize().width; + int height = getSize().height; + + // (JY addition: three lines are new) + int level = + minLevels.get(v).intValue(); + int minY = (int) (level * height / (graphHeight * SPACEFACTOR)); + int maxY = + level == 0 + ? (int) (height / (graphHeight * SPACEFACTOR * 2)) + : height; + + // JY added 2* - double the sideways repulsion. + vd.dx += 2 * vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + + // JY Addition: Attract the vertex towards it's minimumLevel + // height. + double delta = xyd.getY() - minY; + vd.dy -= delta * LEVELATTRACTIONRATE; + if (level == 0) + vd.dy -= delta * LEVELATTRACTIONRATE; + // twice as much at the top. + + // JY addition: + meanSquareVel += (vd.dx * vd.dx + vd.dy * vd.dy); + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)) , xyd.getY()+Math.max(-5, Math.min(5, vd.dy)) ); + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY()); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); + } + + // (JY addition: These two lines replaced 0 with minY) + if (xyd.getY() < minY) { + xyd.setLocation(xyd.getX(), minY); + // (JY addition: replace height with maxY) + } else if (xyd.getY() > maxY) { + xyd.setLocation(xyd.getX(), maxY); + } + + // (JY addition: if there's only one root, anchor it in the + // middle-top of the screen) + if (numRoots == 1 && level == 0) { + xyd.setLocation(width/2, xyd.getY()); + } + } + } + //System.out.println("MeanSquareAccel="+meanSquareVel); + if (!stoppingIncrements + && Math.abs(meanSquareVel - oldMSV) < MSV_THRESHOLD) { + stoppingIncrements = true; + incrementsLeft = COOL_DOWN_INCREMENTS; + } else if ( + stoppingIncrements + && Math.abs(meanSquareVel - oldMSV) <= MSV_THRESHOLD) { + incrementsLeft--; + if (incrementsLeft <= 0) + incrementsLeft = 0; + } + } + + /** + * Override incrementsAreDone so that we can eventually stop. + */ + @Override + public boolean done() { + if (stoppingIncrements && incrementsLeft == 0) + return true; + else + return false; + } + + /** + * Override forceMove so that if someone moves a node, we can re-layout + * everything. + * @param picked the vertex whose location is to be set + * @param x the x coordinate of the location to set + * @param y the y coordinate of the location to set + */ + @Override + public void setLocation(V picked, double x, double y) { + Point2D coord = apply(picked); + coord.setLocation(x,y); + stoppingIncrements = false; + } + + /** + * Override forceMove so that if someone moves a node, we can re-layout + * everything. + * @param picked the vertex whose location is to be set + * @param p the location to set + */ + @Override + public void setLocation(V picked, Point2D p) { + setLocation(picked, p.getX(), p.getY()); + } + + /** + * Overridden relaxEdges. This one reduces the effect of edges between + * greatly different levels. + * + */ + @Override + protected void relaxEdges() { + for(E e : getGraph().getEdges()) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + double vx = p1.getX() - p2.getX(); + double vy = p1.getY() - p2.getY(); + double len = Math.sqrt(vx * vx + vy * vy); + + // JY addition. + int level1 = + minLevels.get(v1).intValue(); + int level2 = + minLevels.get(v2).intValue(); + + double desiredLen = lengthFunction.apply(e); + + // round from zero, if needed [zero would be Bad.]. + len = (len == 0) ? .0001 : len; + + // force factor: optimal length minus actual length, + // is made smaller as the current actual length gets larger. + // why? + + // System.out.println("Desired : " + getLength( e )); + double f = force_multiplier * (desiredLen - len) / len; + + f = f * Math.pow(stretch / 100.0, + (getGraph().degree(v1) + getGraph().degree(v2) -2)); + + // JY addition. If this is an edge which stretches a long way, + // don't be so concerned about it. + if (level1 != level2) + f = f / Math.pow(Math.abs(level2 - level1), 1.5); + + // the actual movement distance 'dx' is the force multiplied by the + // distance to go. + double dx = f * vx; + double dy = f * vy; + SpringVertexData v1D, v2D; + v1D = springVertexData.getUnchecked(v1); + v2D = springVertexData.getUnchecked(v2); + + v1D.edgedx += dx; + v1D.edgedy += dy; + v2D.edgedx += -dx; + v2D.edgedy += -dy; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout2.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ConcurrentModificationException; + +import com.google.common.base.Preconditions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Implements the Fruchterman-Reingold force-directed algorithm for node layout. + * This is an experimental attempt at optimizing {@code FRLayout}; if it is successful + * it will be folded back into {@code FRLayout} (and this class will disappear). + * + *

    Behavior is determined by the following settable parameters: + *

      + *
    • attraction multiplier: how much edges try to keep their vertices together + *
    • repulsion multiplier: how much vertices try to push each other apart + *
    • maximum iterations: how many iterations this algorithm will use before stopping + *
    + * Each of the first two defaults to 0.75; the maximum number of iterations defaults to 700. + + * + * @see "Fruchterman and Reingold, 'Graph Drawing by Force-directed Placement'" + * @see "http://i11www.ilkd.uni-karlsruhe.de/teaching/SS_04/visualisierung/papers/fruchterman91graph.pdf" + * + * @author Tom Nelson + * @author Scott White, Yan-Biao Boey, Danyel Fisher + */ +public class FRLayout2 extends AbstractLayout implements IterativeContext { + + private double forceConstant; + + private double temperature; + + private int currentIteration; + + private int maxIterations = 700; + + protected LoadingCache frVertexData = + CacheBuilder.newBuilder().build(new CacheLoader() { + public Point2D load(V vertex) { + return new Point2D.Double(); + } + }); + + private double attraction_multiplier = 0.75; + + private double attraction_constant; + + private double repulsion_multiplier = 0.75; + + private double repulsion_constant; + + private double max_dimension; + + private Rectangle2D innerBounds = new Rectangle2D.Double(); + + private boolean checked = false; + + public FRLayout2(Graph g) { + super(g); + } + + public FRLayout2(Graph g, Dimension d) { + super(g, new RandomLocationTransformer(d), d); + max_dimension = Math.max(d.height, d.width); + initialize(); + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + double t = size.width/50.0; + innerBounds.setFrameFromDiagonal(t,t,size.width-t,size.height-t); + max_dimension = Math.max(size.height, size.width); + } + + public void setAttractionMultiplier(double attraction) { + this.attraction_multiplier = attraction; + } + + public void setRepulsionMultiplier(double repulsion) { + this.repulsion_multiplier = repulsion; + } + + public void reset() { + doInit(); + } + + public void initialize() { + doInit(); + } + + private void doInit() { + Graph graph = getGraph(); + Dimension d = getSize(); + if(graph != null && d != null) { + currentIteration = 0; + temperature = d.getWidth() / 10; + + forceConstant = + Math + .sqrt(d.getHeight() + * d.getWidth() + / graph.getVertexCount()); + + attraction_constant = attraction_multiplier * forceConstant; + repulsion_constant = repulsion_multiplier * forceConstant; + } + } + + private double EPSILON = 0.000001D; + + /** + * Moves the iteration forward one notch, calculation attraction and + * repulsion between vertices and edges and cooling the temperature. + */ + public synchronized void step() { + currentIteration++; + + /** + * Calculate repulsion + */ + while(true) { + + try { + for(V v1 : getGraph().getVertices()) { + calcRepulsion(v1); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + /** + * Calculate attraction + */ + while(true) { + try { + for(E e : getGraph().getEdges()) { + calcAttraction(e); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + + while(true) { + try { + for(V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + calcPositions(v); + } + break; + } catch(ConcurrentModificationException cme) {} + } + cool(); + } + + protected synchronized void calcPositions(V v) { + Point2D fvd = this.frVertexData.getUnchecked(v); + if(fvd == null) return; + Point2D xyd = apply(v); + double deltaLength = Math.max(EPSILON, + Math.sqrt(fvd.getX()*fvd.getX()+fvd.getY()*fvd.getY())); + + double newXDisp = fvd.getX() / deltaLength + * Math.min(deltaLength, temperature); + + Preconditions.checkState(!Double.isNaN(newXDisp), + "Unexpected mathematical result in FRLayout:calcPositions [xdisp]"); + + double newYDisp = fvd.getY() / deltaLength + * Math.min(deltaLength, temperature); + double newX = xyd.getX()+Math.max(-5, Math.min(5,newXDisp)); + double newY = xyd.getY()+Math.max(-5, Math.min(5,newYDisp)); + + newX = Math.max(innerBounds.getMinX(), Math.min(newX, innerBounds.getMaxX())); + newY = Math.max(innerBounds.getMinY(), Math.min(newY, innerBounds.getMaxY())); + + xyd.setLocation(newX, newY); + + } + + protected void calcAttraction(E e) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + boolean v1_locked = isLocked(v1); + boolean v2_locked = isLocked(v2); + + if(v1_locked && v2_locked) { + // both locked, do nothing + return; + } + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + if(p1 == null || p2 == null) return; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, p1.distance(p2)); + + double force = deltaLength / attraction_constant; + + Preconditions.checkState(!Double.isNaN(force), + "Unexpected mathematical result in FRLayout:calcPositions [force]"); + + double dx = xDelta * force; + double dy = yDelta * force; + Point2D fvd1 = frVertexData.getUnchecked(v1); + Point2D fvd2 = frVertexData.getUnchecked(v2); + if(v2_locked) { + // double the offset for v1, as v2 will not be moving in + // the opposite direction + fvd1.setLocation(fvd1.getX()-2*dx, fvd1.getY()-2*dy); + } else { + fvd1.setLocation(fvd1.getX()-dx, fvd1.getY()-dy); + } + if(v1_locked) { + // double the offset for v2, as v1 will not be moving in + // the opposite direction + fvd2.setLocation(fvd2.getX()+2*dx, fvd2.getY()+2*dy); + } else { + fvd2.setLocation(fvd2.getX()+dx, fvd2.getY()+dy); + } + } + + protected void calcRepulsion(V v1) { + Point2D fvd1 = frVertexData.getUnchecked(v1); + if(fvd1 == null) return; + fvd1.setLocation(0, 0); + boolean v1_locked = isLocked(v1); + + try { + for(V v2 : getGraph().getVertices()) { + + boolean v2_locked = isLocked(v2); + if (v1_locked && v2_locked) continue; + if (v1 != v2) { + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + if(p1 == null || p2 == null) continue; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, p1.distanceSq(p2)); + + double force = (repulsion_constant * repulsion_constant);// / deltaLength; + + double forceOverDeltaLength = force / deltaLength; + + Preconditions.checkState(!Double.isNaN(force), + "Unexpected mathematical result in FRLayout:calcPositions [repulsion]"); + + if(v2_locked) { + // double the offset for v1, as v2 will not be moving in + // the opposite direction + fvd1.setLocation(fvd1.getX()+2 * xDelta * forceOverDeltaLength, + fvd1.getY()+ 2 * yDelta * forceOverDeltaLength); + } else { + fvd1.setLocation(fvd1.getX()+xDelta * forceOverDeltaLength, + fvd1.getY()+yDelta * forceOverDeltaLength); + } + } + } + } catch(ConcurrentModificationException cme) { + calcRepulsion(v1); + } + } + + private void cool() { + temperature *= (1.0 - currentIteration / (double) maxIterations); + } + + public void setMaxIterations(int maxIterations) { + this.maxIterations = maxIterations; + } + + /** + * @return true + */ + public boolean isIncremental() { + return true; + } + + /** + * @return true once the current iteration has passed the maximum count. + */ + public boolean done() { + if (currentIteration > maxIterations || temperature < 1.0/max_dimension) { + if (!checked) + { + checked = true; + } + return true; + } + return false; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/FRLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Implements the Fruchterman-Reingold force-directed algorithm for node layout. + * + *

    Behavior is determined by the following settable parameters: + *

      + *
    • attraction multiplier: how much edges try to keep their vertices together + *
    • repulsion multiplier: how much vertices try to push each other apart + *
    • maximum iterations: how many iterations this algorithm will use before stopping + *
    + * Each of the first two defaults to 0.75; the maximum number of iterations defaults to 700. + * + * @see "Fruchterman and Reingold, 'Graph Drawing by Force-directed Placement'" + * @see "http://i11www.ilkd.uni-karlsruhe.de/teaching/SS_04/visualisierung/papers/fruchterman91graph.pdf" + * @author Scott White, Yan-Biao Boey, Danyel Fisher + */ +public class FRLayout extends AbstractLayout implements IterativeContext { + + private double forceConstant; + + private double temperature; + + private int currentIteration; + + private int mMaxIterations = 700; + + protected LoadingCache frVertexData = + CacheBuilder.newBuilder().build(new CacheLoader() { + public FRVertexData load(V vertex) { + return new FRVertexData(); + } + }); + + private double attraction_multiplier = 0.75; + + private double attraction_constant; + + private double repulsion_multiplier = 0.75; + + private double repulsion_constant; + + private double max_dimension; + + public FRLayout(Graph g) { + super(g); + } + + public FRLayout(Graph g, Dimension d) { + super(g, new RandomLocationTransformer(d), d); + initialize(); + max_dimension = Math.max(d.height, d.width); + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) { + setInitializer(new RandomLocationTransformer(size)); + } + super.setSize(size); + max_dimension = Math.max(size.height, size.width); + } + + public void setAttractionMultiplier(double attraction) { + this.attraction_multiplier = attraction; + } + + public void setRepulsionMultiplier(double repulsion) { + this.repulsion_multiplier = repulsion; + } + + public void reset() { + doInit(); + } + + public void initialize() { + doInit(); + } + + private void doInit() { + Graph graph = getGraph(); + Dimension d = getSize(); + if(graph != null && d != null) { + currentIteration = 0; + temperature = d.getWidth() / 10; + + forceConstant = + Math + .sqrt(d.getHeight() + * d.getWidth() + / graph.getVertexCount()); + + attraction_constant = attraction_multiplier * forceConstant; + repulsion_constant = repulsion_multiplier * forceConstant; + } + } + + private double EPSILON = 0.000001D; + + /** + * Moves the iteration forward one notch, calculation attraction and + * repulsion between vertices and edges and cooling the temperature. + */ + public synchronized void step() { + currentIteration++; + + /** + * Calculate repulsion + */ + while(true) { + + try { + for(V v1 : getGraph().getVertices()) { + calcRepulsion(v1); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + /** + * Calculate attraction + */ + while(true) { + try { + for(E e : getGraph().getEdges()) { + + calcAttraction(e); + } + break; + } catch(ConcurrentModificationException cme) {} + } + + + while(true) { + try { + for(V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + calcPositions(v); + } + break; + } catch(ConcurrentModificationException cme) {} + } + cool(); + } + + protected synchronized void calcPositions(V v) { + FRVertexData fvd = getFRData(v); + if(fvd == null) return; + Point2D xyd = apply(v); + double deltaLength = Math.max(EPSILON, fvd.norm()); + + double newXDisp = fvd.getX() / deltaLength + * Math.min(deltaLength, temperature); + + if (Double.isNaN(newXDisp)) { + throw new IllegalArgumentException( + "Unexpected mathematical result in FRLayout:calcPositions [xdisp]"); } + + double newYDisp = fvd.getY() / deltaLength + * Math.min(deltaLength, temperature); + xyd.setLocation(xyd.getX()+newXDisp, xyd.getY()+newYDisp); + + double borderWidth = getSize().getWidth() / 50.0; + double newXPos = xyd.getX(); + if (newXPos < borderWidth) { + newXPos = borderWidth + Math.random() * borderWidth * 2.0; + } else if (newXPos > (getSize().getWidth() - borderWidth)) { + newXPos = getSize().getWidth() - borderWidth - Math.random() + * borderWidth * 2.0; + } + + double newYPos = xyd.getY(); + if (newYPos < borderWidth) { + newYPos = borderWidth + Math.random() * borderWidth * 2.0; + } else if (newYPos > (getSize().getHeight() - borderWidth)) { + newYPos = getSize().getHeight() - borderWidth + - Math.random() * borderWidth * 2.0; + } + + xyd.setLocation(newXPos, newYPos); + } + + protected void calcAttraction(E e) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + boolean v1_locked = isLocked(v1); + boolean v2_locked = isLocked(v2); + + if(v1_locked && v2_locked) { + // both locked, do nothing + return; + } + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + if(p1 == null || p2 == null) return; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, Math.sqrt((xDelta * xDelta) + + (yDelta * yDelta))); + + double force = (deltaLength * deltaLength) / attraction_constant; + + if (Double.isNaN(force)) { throw new IllegalArgumentException( + "Unexpected mathematical result in FRLayout:calcPositions [force]"); } + + double dx = (xDelta / deltaLength) * force; + double dy = (yDelta / deltaLength) * force; + if(v1_locked == false) { + FRVertexData fvd1 = getFRData(v1); + fvd1.offset(-dx, -dy); + } + if(v2_locked == false) { + FRVertexData fvd2 = getFRData(v2); + fvd2.offset(dx, dy); + } + } + + protected void calcRepulsion(V v1) { + FRVertexData fvd1 = getFRData(v1); + if(fvd1 == null) + return; + fvd1.setLocation(0, 0); + + try { + for(V v2 : getGraph().getVertices()) { + +// if (isLocked(v2)) continue; + if (v1 != v2) { + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + if(p1 == null || p2 == null) continue; + double xDelta = p1.getX() - p2.getX(); + double yDelta = p1.getY() - p2.getY(); + + double deltaLength = Math.max(EPSILON, Math + .sqrt((xDelta * xDelta) + (yDelta * yDelta))); + + double force = (repulsion_constant * repulsion_constant) / deltaLength; + + if (Double.isNaN(force)) { throw new RuntimeException( + "Unexpected mathematical result in FRLayout:calcPositions [repulsion]"); } + + fvd1.offset((xDelta / deltaLength) * force, + (yDelta / deltaLength) * force); + } + } + } catch(ConcurrentModificationException cme) { + calcRepulsion(v1); + } + } + + private void cool() { + temperature *= (1.0 - currentIteration / (double) mMaxIterations); + } + + public void setMaxIterations(int maxIterations) { + mMaxIterations = maxIterations; + } + + protected FRVertexData getFRData(V v) { + return frVertexData.getUnchecked(v); + } + + /** + * @return true + */ + public boolean isIncremental() { + return true; + } + + /** + * @return true once the current iteration has passed the maximum count. + */ + public boolean done() { + if (currentIteration > mMaxIterations || temperature < 1.0/max_dimension) + { + return true; + } + return false; + } + + @SuppressWarnings("serial") + protected static class FRVertexData extends Point2D.Double + { + protected void offset(double x, double y) + { + this.x += x; + this.y += y; + } + + protected double norm() + { + return Math.sqrt(x*x + y*y); + } + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/GraphElementAccessor.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Apr 12, 2005 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Shape; +import java.util.Collection; + +/** + * Interface for coordinate-based selection of graph components. + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public interface GraphElementAccessor +{ + /** + * Returns the vertex, if any, associated with (x, y). + * + * @param layout the layout instance that records the positions for all vertices + * @param x the x coordinate of the pick point + * @param y the y coordinate of the pick point + * @return the vertex associated with (x, y) + */ + V getVertex(Layout layout, double x, double y); + + /** + * @param layout the layout instance that records the positions for all vertices + * @param rectangle the region in which the returned vertices are located + * @return the vertices whose locations given by {@code layout} + * are contained within {@code rectangle} + */ + Collection getVertices(Layout layout, Shape rectangle); + + /** + * @param layout the context in which the location is defined + * @param x the x coordinate of the location + * @param y the y coordinate of the location + * @return an edge which is associated with the location {@code (x,y)} + * as given by {@code layout}, generally by reference to the edge's endpoints + */ + E getEdge(Layout layout, double x, double y); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/ISOMLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,225 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.List; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * Implements a self-organizing map layout algorithm, based on Meyer's + * self-organizing graph methods. + * + * @author Yan Biao Boey + */ +public class ISOMLayout extends AbstractLayout implements IterativeContext { + + protected LoadingCache isomVertexData = + CacheBuilder.newBuilder().build(new CacheLoader() { + public ISOMVertexData load(V vertex) { + return new ISOMVertexData(); + } + }); + + private int maxEpoch; + private int epoch; + + private int radiusConstantTime; + private int radius; + private int minRadius; + + private double adaption; + private double initialAdaption; + private double minAdaption; + + protected GraphElementAccessor elementAccessor = + new RadiusGraphElementAccessor(); + + private double coolingFactor; + + private List queue = new ArrayList(); + private String status = null; + + /** + * @return the current number of epochs and execution status, as a string. + */ + public String getStatus() { + return status; + } + + public ISOMLayout(Graph g) { + super(g); + } + + public void initialize() { + + setInitializer(new RandomLocationTransformer(getSize())); + maxEpoch = 2000; + epoch = 1; + + radiusConstantTime = 100; + radius = 5; + minRadius = 1; + + initialAdaption = 90.0D / 100.0D; + adaption = initialAdaption; + minAdaption = 0; + + //factor = 0; //Will be set later on + coolingFactor = 2; + + //temperature = 0.03; + //initialJumpRadius = 100; + //jumpRadius = initialJumpRadius; + + //delay = 100; + } + + + /** + * Advances the current positions of the graph elements. + */ + public void step() { + status = "epoch: " + epoch + "; "; + if (epoch < maxEpoch) { + adjust(); + updateParameters(); + status += " status: running"; + } else { + status += "adaption: " + adaption + "; "; + status += "status: done"; +// done = true; + } + } + + private synchronized void adjust() { + //Generate random position in graph space + Point2D tempXYD = new Point2D.Double(); + + // creates a new XY data location + tempXYD.setLocation(10 + Math.random() * getSize().getWidth(), + 10 + Math.random() * getSize().getHeight()); + + //Get closest vertex to random position + V winner = elementAccessor.getVertex(this, tempXYD.getX(), tempXYD.getY()); + + while(true) { + try { + for(V v : getGraph().getVertices()) { + ISOMVertexData ivd = getISOMVertexData(v); + ivd.distance = 0; + ivd.visited = false; + } + break; + } catch(ConcurrentModificationException cme) {} + } + adjustVertex(winner, tempXYD); + } + + private synchronized void updateParameters() { + epoch++; + double factor = Math.exp(-1 * coolingFactor * (1.0 * epoch / maxEpoch)); + adaption = Math.max(minAdaption, factor * initialAdaption); + //jumpRadius = (int) factor * jumpRadius; + //temperature = factor * temperature; + if ((radius > minRadius) && (epoch % radiusConstantTime == 0)) { + radius--; + } + } + + private synchronized void adjustVertex(V v, Point2D tempXYD) { + queue.clear(); + ISOMVertexData ivd = getISOMVertexData(v); + ivd.distance = 0; + ivd.visited = true; + queue.add(v); + V current; + + while (!queue.isEmpty()) { + current = queue.remove(0); + ISOMVertexData currData = getISOMVertexData(current); + Point2D currXYData = apply(current); + + double dx = tempXYD.getX() - currXYData.getX(); + double dy = tempXYD.getY() - currXYData.getY(); + double factor = adaption / Math.pow(2, currData.distance); + + currXYData.setLocation(currXYData.getX()+(factor*dx), currXYData.getY()+(factor*dy)); + + if (currData.distance < radius) { + Collection s = getGraph().getNeighbors(current); + while(true) { + try { + for(V child : s) { + ISOMVertexData childData = getISOMVertexData(child); + if (childData != null && !childData.visited) { + childData.visited = true; + childData.distance = currData.distance + 1; + queue.add(child); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + } + } + } + + protected ISOMVertexData getISOMVertexData(V v) { + return isomVertexData.getUnchecked(v); + } + + /** + * This one is an incremental visualization. + * @return true is the layout algorithm is incremental, false otherwise + */ + public boolean isIncremental() { + return true; + } + + /** + * Returns true if the vertex positions are no longer being + * updated. Currently ISOMLayout stops updating vertex + * positions after a certain number of iterations have taken place. + * @return true if the vertex position updates have stopped, + * false otherwise + */ + public boolean done() { + return epoch >= maxEpoch; + } + + protected static class ISOMVertexData { + int distance; + boolean visited; + + protected ISOMVertexData() { + distance = 0; + visited = false; + } + } + + /** + * Resets the layout iteration count to 0, which allows the layout algorithm to + * continue updating vertex positions. + */ + public void reset() { + epoch = 0; + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/KKLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; +/* + * This source is under the same license with JUNG. + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.algorithms.shortestpath.DistanceStatistics; +import edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * Implements the Kamada-Kawai algorithm for node layout. + * Does not respect filter calls, and sometimes crashes when the view changes to it. + * + * @see "Tomihisa Kamada and Satoru Kawai: An algorithm for drawing general indirect graphs. Information Processing Letters 31(1):7-15, 1989" + * @see "Tomihisa Kamada: On visualization of abstract objects and relations. Ph.D. dissertation, Dept. of Information Science, Univ. of Tokyo, Dec. 1988." + * + * @author Masanori Harada + */ +public class KKLayout extends AbstractLayout implements IterativeContext { + + private double EPSILON = 0.1d; + + private int currentIteration; + private int maxIterations = 2000; + private String status = "KKLayout"; + + private double L; // the ideal length of an edge + private double K = 1; // arbitrary const number + private double[][] dm; // distance matrix + + private boolean adjustForGravity = true; + private boolean exchangeVertices = true; + + private V[] vertices; + private Point2D[] xydata; + + /** + * Retrieves graph distances between vertices of the visible graph + */ + protected Distance distance; + + /** + * The diameter of the visible graph. In other words, the maximum over all pairs + * of vertices of the length of the shortest path between a and bf the visible graph. + */ + protected double diameter; + + /** + * A multiplicative factor which partly specifies the "preferred" length of an edge (L). + */ + private double length_factor = 0.9; + + /** + * A multiplicative factor which specifies the fraction of the graph's diameter to be + * used as the inter-vertex distance between disconnected vertices. + */ + private double disconnected_multiplier = 0.5; + + public KKLayout(Graph g) + { + this(g, new UnweightedShortestPath(g)); + } + + /** + * Creates an instance for the specified graph and distance metric. + * @param g the graph on which the layout algorithm is to operate + * @param distance specifies the distance between pairs of vertices + */ + public KKLayout(Graph g, Distance distance){ + super(g); + this.distance = distance; + } + + /** + * @param length_factor a multiplicative factor which partially specifies + * the preferred length of an edge + */ + public void setLengthFactor(double length_factor){ + this.length_factor = length_factor; + } + + /** + * @param disconnected_multiplier a multiplicative factor that specifies the fraction of the + * graph's diameter to be used as the inter-vertex distance between disconnected vertices + */ + public void setDisconnectedDistanceMultiplier(double disconnected_multiplier){ + this.disconnected_multiplier = disconnected_multiplier; + } + + /** + * @return a string with information about the current status of the algorithm. + */ + public String getStatus() { + return status + this.getSize(); + } + + public void setMaxIterations(int maxIterations) { + this.maxIterations = maxIterations; + } + + /** + * @return true + */ + public boolean isIncremental() { + return true; + } + + /** + * @return true if the current iteration has passed the maximum count. + */ + public boolean done() { + if (currentIteration > maxIterations) { + return true; + } + return false; + } + + @SuppressWarnings("unchecked") + public void initialize() { + currentIteration = 0; + + if(graph != null && size != null) { + + double height = size.getHeight(); + double width = size.getWidth(); + + int n = graph.getVertexCount(); + dm = new double[n][n]; + vertices = (V[])graph.getVertices().toArray(); + xydata = new Point2D[n]; + + // assign IDs to all visible vertices + while(true) { + try { + int index = 0; + for(V v : graph.getVertices()) { + Point2D xyd = apply(v); + vertices[index] = v; + xydata[index] = xyd; + index++; + } + break; + } catch(ConcurrentModificationException cme) {} + } + + diameter = DistanceStatistics.diameter(graph, distance, true); + + double L0 = Math.min(height, width); + L = (L0 / diameter) * length_factor; // length_factor used to be hardcoded to 0.9 + //L = 0.75 * Math.sqrt(height * width / n); + + for (int i = 0; i < n - 1; i++) { + for (int j = i + 1; j < n; j++) { + Number d_ij = distance.getDistance(vertices[i], vertices[j]); + Number d_ji = distance.getDistance(vertices[j], vertices[i]); + double dist = diameter * disconnected_multiplier; + if (d_ij != null) + dist = Math.min(d_ij.doubleValue(), dist); + if (d_ji != null) + dist = Math.min(d_ji.doubleValue(), dist); + dm[i][j] = dm[j][i] = dist; + } + } + } + } + + public void step() { + try { + currentIteration++; + double energy = calcEnergy(); + status = "Kamada-Kawai V=" + getGraph().getVertexCount() + + "(" + getGraph().getVertexCount() + ")" + + " IT: " + currentIteration + + " E=" + energy + ; + + int n = getGraph().getVertexCount(); + if (n == 0) + return; + + double maxDeltaM = 0; + int pm = -1; // the node having max deltaM + for (int i = 0; i < n; i++) { + if (isLocked(vertices[i])) + continue; + double deltam = calcDeltaM(i); + + if (maxDeltaM < deltam) { + maxDeltaM = deltam; + pm = i; + } + } + if (pm == -1) + return; + + for (int i = 0; i < 100; i++) { + double[] dxy = calcDeltaXY(pm); + xydata[pm].setLocation(xydata[pm].getX()+dxy[0], xydata[pm].getY()+dxy[1]); + + double deltam = calcDeltaM(pm); + if (deltam < EPSILON) + break; + } + + if (adjustForGravity) + adjustForGravity(); + + if (exchangeVertices && maxDeltaM < EPSILON) { + energy = calcEnergy(); + for (int i = 0; i < n - 1; i++) { + if (isLocked(vertices[i])) + continue; + for (int j = i + 1; j < n; j++) { + if (isLocked(vertices[j])) + continue; + double xenergy = calcEnergyIfExchanged(i, j); + if (energy > xenergy) { + double sx = xydata[i].getX(); + double sy = xydata[i].getY(); + xydata[i].setLocation(xydata[j]); + xydata[j].setLocation(sx, sy); + return; + } + } + } + } + } + finally { +// fireStateChanged(); + } + } + + /** + * Shift all vertices so that the center of gravity is located at + * the center of the screen. + */ + public void adjustForGravity() { + Dimension d = getSize(); + double height = d.getHeight(); + double width = d.getWidth(); + double gx = 0; + double gy = 0; + for (int i = 0; i < xydata.length; i++) { + gx += xydata[i].getX(); + gy += xydata[i].getY(); + } + gx /= xydata.length; + gy /= xydata.length; + double diffx = width / 2 - gx; + double diffy = height / 2 - gy; + for (int i = 0; i < xydata.length; i++) { + xydata[i].setLocation(xydata[i].getX()+diffx, xydata[i].getY()+diffy); + } + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + } + + public void setAdjustForGravity(boolean on) { + adjustForGravity = on; + } + + public boolean getAdjustForGravity() { + return adjustForGravity; + } + + /** + * Enable or disable the local minimum escape technique by + * exchanging vertices. + * @param on iff the local minimum escape technique is to be enabled + */ + public void setExchangeVertices(boolean on) { + exchangeVertices = on; + } + + public boolean getExchangeVertices() { + return exchangeVertices; + } + + /** + * Determines a step to new position of the vertex m. + */ + private double[] calcDeltaXY(int m) { + double dE_dxm = 0; + double dE_dym = 0; + double d2E_d2xm = 0; + double d2E_dxmdym = 0; + double d2E_dymdxm = 0; + double d2E_d2ym = 0; + + for (int i = 0; i < vertices.length; i++) { + if (i != m) { + + double dist = dm[m][i]; + double l_mi = L * dist; + double k_mi = K / (dist * dist); + double dx = xydata[m].getX() - xydata[i].getX(); + double dy = xydata[m].getY() - xydata[i].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + double ddd = d * d * d; + + dE_dxm += k_mi * (1 - l_mi / d) * dx; + dE_dym += k_mi * (1 - l_mi / d) * dy; + d2E_d2xm += k_mi * (1 - l_mi * dy * dy / ddd); + d2E_dxmdym += k_mi * l_mi * dx * dy / ddd; + d2E_d2ym += k_mi * (1 - l_mi * dx * dx / ddd); + } + } + // d2E_dymdxm equals to d2E_dxmdym. + d2E_dymdxm = d2E_dxmdym; + + double denomi = d2E_d2xm * d2E_d2ym - d2E_dxmdym * d2E_dymdxm; + double deltaX = (d2E_dxmdym * dE_dym - d2E_d2ym * dE_dxm) / denomi; + double deltaY = (d2E_dymdxm * dE_dxm - d2E_d2xm * dE_dym) / denomi; + return new double[]{deltaX, deltaY}; + } + + /** + * Calculates the gradient of energy function at the vertex m. + */ + private double calcDeltaM(int m) { + double dEdxm = 0; + double dEdym = 0; + for (int i = 0; i < vertices.length; i++) { + if (i != m) { + double dist = dm[m][i]; + double l_mi = L * dist; + double k_mi = K / (dist * dist); + + double dx = xydata[m].getX() - xydata[i].getX(); + double dy = xydata[m].getY() - xydata[i].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + double common = k_mi * (1 - l_mi / d); + dEdxm += common * dx; + dEdym += common * dy; + } + } + return Math.sqrt(dEdxm * dEdxm + dEdym * dEdym); + } + + /** + * Calculates the energy function E. + */ + private double calcEnergy() { + double energy = 0; + for (int i = 0; i < vertices.length - 1; i++) { + for (int j = i + 1; j < vertices.length; j++) { + double dist = dm[i][j]; + double l_ij = L * dist; + double k_ij = K / (dist * dist); + double dx = xydata[i].getX() - xydata[j].getX(); + double dy = xydata[i].getY() - xydata[j].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + + energy += k_ij / 2 * (dx * dx + dy * dy + l_ij * l_ij - + 2 * l_ij * d); + } + } + return energy; + } + + /** + * Calculates the energy function E as if positions of the + * specified vertices are exchanged. + */ + private double calcEnergyIfExchanged(int p, int q) { + if (p >= q) + throw new RuntimeException("p should be < q"); + double energy = 0; // < 0 + for (int i = 0; i < vertices.length - 1; i++) { + for (int j = i + 1; j < vertices.length; j++) { + int ii = i; + int jj = j; + if (i == p) ii = q; + if (j == q) jj = p; + + double dist = dm[i][j]; + double l_ij = L * dist; + double k_ij = K / (dist * dist); + double dx = xydata[ii].getX() - xydata[jj].getX(); + double dy = xydata[ii].getY() - xydata[jj].getY(); + double d = Math.sqrt(dx * dx + dy * dy); + + energy += k_ij / 2 * (dx * dx + dy * dy + l_ij * l_ij - + 2 * l_ij * d); + } + } + return energy; + } + + public void reset() { + currentIteration = 0; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/LayoutDecorator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; + +/** + * a pure decorator for the Layout interface. Intended to be overridden + * to provide specific behavior decoration + * + * @author Tom Nelson + * + */ +public abstract class LayoutDecorator implements Layout, IterativeContext { + + protected Layout delegate; + + /** + * Creates an instance backed by the specified {@code delegate}. + * @param delegate the layout to which this instance is delegating + */ + public LayoutDecorator(Layout delegate) { + this.delegate = delegate; + } + + /** + * @return the backing (delegate) layout. + */ + public Layout getDelegate() { + return delegate; + } + + public void setDelegate(Layout delegate) { + this.delegate = delegate; + } + + public void step() { + if(delegate instanceof IterativeContext) { + ((IterativeContext)delegate).step(); + } + } + + public void initialize() { + delegate.initialize(); + } + + public void setInitializer(Function initializer) { + delegate.setInitializer(initializer); + } + + public void setLocation(V v, Point2D location) { + delegate.setLocation(v, location); + } + + public Dimension getSize() { + return delegate.getSize(); + } + + public Graph getGraph() { + return delegate.getGraph(); + } + + public Point2D transform(V v) { + return delegate.apply(v); + } + + public boolean done() { + if(delegate instanceof IterativeContext) { + return ((IterativeContext)delegate).done(); + } + return true; + } + + public void lock(V v, boolean state) { + delegate.lock(v, state); + } + + public boolean isLocked(V v) { + return delegate.isLocked(v); + } + + public void setSize(Dimension d) { + delegate.setSize(d); + } + + public void reset() { + delegate.reset(); + } + + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/Layout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A generalized interface is a mechanism for returning (x,y) coordinates + * from vertices. In general, most of these methods are used to both control and + * get information from the layout algorithm. + *

    + * @author danyelf + * @author tom nelson + */ +public interface Layout extends Function { + + /** + * Initializes fields in the node that may not have + * been set during the constructor. Must be called before + * the iterations begin. + */ + void initialize(); + + /** + * @param initializer a function that specifies initial locations for all vertices + */ + void setInitializer(Function initializer); + + /** + * @param graph the graph that this algorithm is to operate on + */ + void setGraph(Graph graph); + + /** + * @return the graph that this Layout refers to + */ + Graph getGraph(); + + void reset(); + + /** + * @param d the space to use to lay out this graph + */ + void setSize(Dimension d); + + /** + * @return the current size of the visualization's space + */ + Dimension getSize(); + + + /** + * Locks or unlocks the specified vertex. Locking the vertex fixes it at its current position, + * so that it will not be affected by the layout algorithm. Unlocking it allows the layout + * algorithm to change the vertex's position. + * + * @param v the vertex to lock/unlock + * @param state {@code true} to lock the vertex, {@code false} to unlock it + */ + void lock(V v, boolean state); + + /** + * @param v the vertex whose locked state is being queried + * @return true if the position of vertex v is locked + */ + boolean isLocked(V v); + + /** + * Changes the layout coordinates of {@code v} to {@code location}. + * @param v the vertex whose location is to be specified + * @param location the coordinates of the specified location + */ + void setLocation(V v, Point2D location); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,39 @@ + + + + + + + +Algorithms for assigning 2D coordinates (typically used for graph visualizations) +to vertices. +Current layout algorithms include: +

      +
    • Layout, AbstractLayout: interface and abstract class defining the Layout contract and handling +some common implementation details +
    • AggregateLayout: allows multiple layouts to be combined and manipulated as one layout +
    • BalloonLayout: places vertices on nested circles (trees/forests only) +
    • CircleLayout: places vertices on a circle +
    • DAGLayout: places vertices in a hierarchy (directed acyclic graphs only) +
    • FRLayout: Fruchterman-Reingold algorithm (force-directed) +
    • ISOMLayout: self-organizing map layout +
    • KKLayout: Kamada-Kawai algorithm (tries to maintain specified distances) +
    • RadialTreeLayout: places vertices on concentric circles (trees only) +
    • SpringLayout: simple force-directed layout +
    • StaticLayout: places vertices at user-specified locations +
    • TreeLayout: simple tree/forest layout +
    + +Rendering and other aspects of visualization are handled in the visualization package. + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/PolarPoint.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.geom.Point2D; + +/** + * Represents a point in polar coordinates: distance and angle from the origin. + * Includes conversions between polar and Cartesian + * coordinates (Point2D). + * + * @author Tom Nelson - tomnelson@dev.java.net + */ +public class PolarPoint +{ + double theta; + double radius; + + /** + * Creates a new instance with radius and angle each 0. + */ + public PolarPoint() { + this(0,0); + } + + /** + * Creates a new instance with the specified radius and angle. + * @param theta the angle of the point to create + * @param radius the distance from the origin of the point to create + */ + public PolarPoint(double theta, double radius) { + this.theta = theta; + this.radius = radius; + } + + /** + * @return the angle for this point + */ + public double getTheta() { return theta; } + + /** + * @return the radius for this point + */ + public double getRadius() { return radius; } + + public void setTheta(double theta) { this.theta = theta; } + + public void setRadius(double radius) { this.radius = radius; } + + /** + * @param polar the input location to convert + * @return the result of converting polar to Cartesian coordinates. + */ + public static Point2D polarToCartesian(PolarPoint polar) { + return polarToCartesian(polar.getTheta(), polar.getRadius()); + } + + /** + * @param theta the angle of the input location + * @param radius the distance from the origin of the input location + * @return the result of converting (theta, radius) to Cartesian coordinates. + */ + public static Point2D polarToCartesian(double theta, double radius) { + return new Point2D.Double(radius*Math.cos(theta), radius*Math.sin(theta)); + } + + /** + * @param point the input location + * @return the result of converting point to polar coordinates. + */ + public static PolarPoint cartesianToPolar(Point2D point) { + return cartesianToPolar(point.getX(), point.getY()); + } + + /** + * @param x the x coordinate of the input location + * @param y the y coordinate of the input location + * @return the result of converting (x, y) to polar coordinates. + */ + public static PolarPoint cartesianToPolar(double x, double y) { + double theta = Math.atan2(y,x); + double radius = Math.sqrt(x*x+y*y); + return new PolarPoint(theta, radius); + } + + @Override + public String toString() { + return "PolarPoint[" + radius + "," + theta +"]"; + } + + /** + * Sets the angle and radius of this point to those of {@code p}. + * @param p the point whose location is copied into this instance + */ + public void setLocation(PolarPoint p) { + this.theta = p.getTheta(); + this.radius = p.getRadius(); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadialTreeLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Forest; + +/** + * A radial layout for Tree or Forest graphs. + * + * @author Tom Nelson + * + */ +public class RadialTreeLayout extends TreeLayout { + + protected Map polarLocations; + + public RadialTreeLayout(Forest g) { + this(g, DEFAULT_DISTX, DEFAULT_DISTY); + } + + public RadialTreeLayout(Forest g, int distx) { + this(g, distx, DEFAULT_DISTY); + } + + public RadialTreeLayout(Forest g, int distx, int disty) { + super(g, distx, disty); + } + + @Override + protected void buildTree() { + super.buildTree(); + this.polarLocations = new HashMap(); + setRadialLocations(); + } + + @Override + public void setSize(Dimension size) { + this.size = size; + buildTree(); + } + + @Override + protected void setCurrentPositionFor(V vertex) { + locations.getUnchecked(vertex).setLocation(m_currentPoint); + } + + @Override + public void setLocation(V v, Point2D location) + { + Point2D c = getCenter(); + Point2D pv = new Point2D.Double(location.getX() - c.getX(), + location.getY() - c.getY()); + PolarPoint newLocation = PolarPoint.cartesianToPolar(pv); + PolarPoint currentLocation = polarLocations.get(v); + if (currentLocation == null) + polarLocations.put(v, newLocation); + else + currentLocation.setLocation(newLocation); + } + + /** + * @return a map from vertices to their locations in polar coordinates. + */ + public Map getPolarLocations() { + return polarLocations; + } + + @Override + public Point2D apply(V v) { + PolarPoint pp = polarLocations.get(v); + double centerX = getSize().getWidth()/2; + double centerY = getSize().getHeight()/2; + Point2D cartesian = PolarPoint.polarToCartesian(pp); + cartesian.setLocation(cartesian.getX()+centerX,cartesian.getY()+centerY); + return cartesian; + } + + private Point2D getMaxXY() { + double maxx = 0; + double maxy = 0; + for(Point2D p : locations.asMap().values()) { + maxx = Math.max(maxx, p.getX()); + maxy = Math.max(maxy, p.getY()); + } + return new Point2D.Double(maxx,maxy); + } + + private void setRadialLocations() { + Point2D max = getMaxXY(); + double maxx = max.getX(); + double maxy = max.getY(); + maxx = Math.max(maxx, size.width); + double theta = 2*Math.PI/maxx; + + double deltaRadius = size.width/2/maxy; + for(Map.Entry entry : locations.asMap().entrySet()) { + V v = entry.getKey(); + Point2D p = entry.getValue(); + PolarPoint polarPoint = + new PolarPoint(p.getX()*theta, (p.getY() - this.distY)*deltaRadius); + polarLocations.put(v, polarPoint); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/RadiusGraphElementAccessor.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Apr 12, 2005 + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * Simple implementation of PickSupport that returns the vertex or edge + * that is closest to the specified location. This implementation + * provides the same picking options that were available in + * previous versions of AbstractLayout. + * + *

    No element will be returned that is farther away than the specified + * maximum distance. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public class RadiusGraphElementAccessor implements GraphElementAccessor { + + protected double maxDistance; + + /** + * Creates an instance with an effectively infinite default maximum distance. + */ + public RadiusGraphElementAccessor() { + this(Math.sqrt(Double.MAX_VALUE - 1000)); + } + + /** + * Creates an instance with the specified default maximum distance. + * @param maxDistance the maximum distance at which any element can be from a specified location + * and still be returned + */ + public RadiusGraphElementAccessor(double maxDistance) { + this.maxDistance = maxDistance; + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of maxDistance. Iterates through all + * visible vertices and checks their distance from the click. Override this + * method to provide a more efficient implementation. + * + * @param layout the context in which the location is defined + * @param x the x coordinate of the location + * @param y the y coordinate of the location + * @return a vertex which is associated with the location {@code (x,y)} + * as given by {@code layout} + */ + public V getVertex(Layout layout, double x, double y) { + return getVertex(layout, x, y, this.maxDistance); + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of {@code maxDistance}. Iterates through all + * visible vertices and checks their distance from the location. Override this + * method to provide a more efficient implementation. + * + * @param layout the context in which the location is defined + * @param x the x coordinate of the location + * @param y the y coordinate of the location + * @param maxDistance the maximum distance at which any element can be from a specified location + * and still be returned + * @return a vertex which is associated with the location {@code (x,y)} + * as given by {@code layout} + */ + public V getVertex(Layout layout, double x, double y, double maxDistance) { + double minDistance = maxDistance * maxDistance; + V closest = null; + while(true) { + try { + for(V v : layout.getGraph().getVertices()) { + + Point2D p = layout.apply(v); + double dx = p.getX() - x; + double dy = p.getY() - y; + double dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = v; + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + public Collection getVertices(Layout layout, Shape rectangle) { + Set pickedVertices = new HashSet(); + while(true) { + try { + for(V v : layout.getGraph().getVertices()) { + + Point2D p = layout.apply(v); + if(rectangle.contains(p)) { + pickedVertices.add(v); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return pickedVertices; + } + + public E getEdge(Layout layout, double x, double y) { + return getEdge(layout, x, y, this.maxDistance); + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * whose endpoints are < {@code maxDistance}. Iterates through all + * visible vertices and checks their distance from the location. Override this + * method to provide a more efficient implementation. + * + * @param layout the context in which the location is defined + * @param x the x coordinate of the location + * @param y the y coordinate of the location + * @param maxDistance the maximum distance at which any element can be from a specified location + * and still be returned + * @return an edge which is associated with the location {@code (x,y)} + * as given by {@code layout} + */ + public E getEdge(Layout layout, double x, double y, double maxDistance) { + double minDistance = maxDistance * maxDistance; + E closest = null; + while(true) { + try { + for(E e : layout.getGraph().getEdges()) { + + // Could replace all this set stuff with getFrom_internal() etc. + Graph graph = layout.getGraph(); + Collection vertices = graph.getIncidentVertices(e); + Iterator vertexIterator = vertices.iterator(); + V v1 = vertexIterator.next(); + V v2 = vertexIterator.next(); + // Get coords + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + double x1 = p1.getX(); + double y1 = p1.getY(); + double x2 = p2.getX(); + double y2 = p2.getY(); + // Calculate location on line closest to (x,y) + // First, check that v1 and v2 are not coincident. + if (x1 == x2 && y1 == y2) + continue; + double b = + ((y - y1) * (y2 - y1) + (x - x1) * (x2 - x1)) + / ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + // + double distance2; // square of the distance + if (b <= 0) + distance2 = (x - x1) * (x - x1) + (y - y1) * (y - y1); + else if (b >= 1) + distance2 = (x - x2) * (x - x2) + (y - y2) * (y - y2); + else { + double x3 = x1 + b * (x2 - x1); + double y3 = y1 + b * (y2 - y1); + distance2 = (x - x3) * (x - x3) + (y - y3) * (y - y3); + } + + if (distance2 < minDistance) { + minDistance = distance2; + closest = e; + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout2.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + +/** + * The SpringLayout package represents a visualization of a set of nodes. The + * SpringLayout, which is initialized with a Graph, assigns X/Y locations to + * each node. When called relax(), the SpringLayout moves the + * visualization forward one step. + * + * + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class SpringLayout2 extends SpringLayout +{ + protected int currentIteration; + protected int averageCounter; + protected int loopCountMax = 4; + protected boolean done; + + protected Point2D averageDelta = new Point2D.Double(); + + /** + * Constructor for a SpringLayout for a raw graph with associated + * dimension--the input knows how big the graph is. Defaults to the unit + * length function. + * @param g the graph on which the layout algorithm is to operate + */ + public SpringLayout2(Graph g) { + super(g); + } + + /** + * Constructor for a SpringLayout for a raw graph with associated component. + * + * @param g the {@code Graph} to lay out + * @param length_function provides a length for each edge + */ + public SpringLayout2(Graph g, Function length_function) + { + super(g, length_function); + } + + /** + * Relaxation step. Moves all nodes a smidge. + */ + @Override + public void step() { + super.step(); + currentIteration++; + testAverageDeltas(); + } + + private void testAverageDeltas() { + double dx = this.averageDelta.getX(); + double dy = this.averageDelta.getY(); + if(Math.abs(dx) < .001 && Math.abs(dy) < .001) { + done = true; + System.err.println("done, dx="+dx+", dy="+dy); + } + if(currentIteration > loopCountMax) { + this.averageDelta.setLocation(0,0); + averageCounter = 0; + currentIteration = 0; + } + } + + @Override + protected void moveNodes() { + synchronized (getSize()) { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + SpringVertexData vd = springVertexData.getUnchecked(v); + if(vd == null) continue; + Point2D xyd = apply(v); + + vd.dx += vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + +// int currentCount = currentIteration % this.loopCountMax; +// System.err.println(averageCounter+" --- vd.dx="+vd.dx+", vd.dy="+vd.dy); +// System.err.println("averageDelta was "+averageDelta); + + averageDelta.setLocation( + ((averageDelta.getX() * averageCounter) + vd.dx) / (averageCounter+1), + ((averageDelta.getY() * averageCounter) + vd.dy) / (averageCounter+1) + ); +// System.err.println("averageDelta now "+averageDelta); +// System.err.println(); + averageCounter++; + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)), + xyd.getY()+Math.max(-5, Math.min(5, vd.dy))); + + Dimension d = getSize(); + int width = d.width; + int height = d.height; + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY());// setX(0); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); //setX(width); + } + if (xyd.getY() < 0) { + xyd.setLocation(xyd.getX(),0);//setY(0); + } else if (xyd.getY() > height) { + xyd.setLocation(xyd.getX(), height); //setY(height); + } + + } + } catch(ConcurrentModificationException cme) { + moveNodes(); + } + } + } + + @Override + public boolean done() { + return done; + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/SpringLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * The SpringLayout package represents a visualization of a set of nodes. The + * SpringLayout, which is initialized with a Graph, assigns X/Y locations to + * each node. When called relax(), the SpringLayout moves the + * visualization forward one step. + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class SpringLayout extends AbstractLayout implements IterativeContext { + + protected double stretch = 0.70; + protected Function lengthFunction; + protected int repulsion_range_sq = 100 * 100; + protected double force_multiplier = 1.0 / 3.0; + + protected LoadingCache springVertexData = + CacheBuilder.newBuilder().build(new CacheLoader() { + public SpringVertexData load(V vertex) { + return new SpringVertexData(); + } + }); +// protected Map springVertexData = +// new MapMaker().makeComputingMap(new Function(){ +// public SpringVertexData apply(V arg0) { +// return new SpringVertexData(); +// }}); + + /** + * Constructor for a SpringLayout for a raw graph with associated + * dimension--the input knows how big the graph is. Defaults to the unit + * length function. + * @param g the graph on which the layout algorithm is to operate + */ + @SuppressWarnings("unchecked") + public SpringLayout(Graph g) { + this(g, (Function)Functions.constant(30)); + } + + /** + * Constructor for a SpringLayout for a raw graph with associated component. + * + * @param g the graph on which the layout algorithm is to operate + * @param length_function provides a length for each edge + */ + public SpringLayout(Graph g, Function length_function) + { + super(g); + this.lengthFunction = length_function; + } + + /** + * @return the current value for the stretch parameter + */ + public double getStretch() { + return stretch; + } + + @Override + public void setSize(Dimension size) { + if(initialized == false) + setInitializer(new RandomLocationTransformer(size)); + super.setSize(size); + } + + /** + *

    Sets the stretch parameter for this instance. This value + * specifies how much the degrees of an edge's incident vertices + * should influence how easily the endpoints of that edge + * can move (that is, that edge's tendency to change its length). + * + *

    The default value is 0.70. Positive values less than 1 cause + * high-degree vertices to move less than low-degree vertices, and + * values > 1 cause high-degree vertices to move more than + * low-degree vertices. Negative values will have unpredictable + * and inconsistent results. + * @param stretch the stretch parameter + */ + public void setStretch(double stretch) { + this.stretch = stretch; + } + + public int getRepulsionRange() { + return (int)(Math.sqrt(repulsion_range_sq)); + } + + /** + * Sets the node repulsion range (in drawing area units) for this instance. + * Outside this range, nodes do not repel each other. The default value + * is 100. Negative values are treated as their positive equivalents. + * @param range the maximum repulsion range + */ + public void setRepulsionRange(int range) { + this.repulsion_range_sq = range * range; + } + + public double getForceMultiplier() { + return force_multiplier; + } + + /** + * Sets the force multiplier for this instance. This value is used to + * specify how strongly an edge "wants" to be its default length + * (higher values indicate a greater attraction for the default length), + * which affects how much its endpoints move at each timestep. + * The default value is 1/3. A value of 0 turns off any attempt by the + * layout to cause edges to conform to the default length. Negative + * values cause long edges to get longer and short edges to get shorter; use + * at your own risk. + * @param force an energy field created by all living things that binds the galaxy together + */ + public void setForceMultiplier(double force) { + this.force_multiplier = force; + } + + public void initialize() { + } + + /** + * Relaxation step. Moves all nodes a smidge. + */ + public void step() { + try { + for(V v : getGraph().getVertices()) { + SpringVertexData svd = springVertexData.getUnchecked(v); + if (svd == null) { + continue; + } + svd.dx /= 4; + svd.dy /= 4; + svd.edgedx = svd.edgedy = 0; + svd.repulsiondx = svd.repulsiondy = 0; + } + } catch(ConcurrentModificationException cme) { + step(); + } + + relaxEdges(); + calculateRepulsion(); + moveNodes(); + } + + protected void relaxEdges() { + try { + for(E e : getGraph().getEdges()) { + Pair endpoints = getGraph().getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = apply(v1); + Point2D p2 = apply(v2); + if(p1 == null || p2 == null) continue; + double vx = p1.getX() - p2.getX(); + double vy = p1.getY() - p2.getY(); + double len = Math.sqrt(vx * vx + vy * vy); + + double desiredLen = lengthFunction.apply(e); + + // round from zero, if needed [zero would be Bad.]. + len = (len == 0) ? .0001 : len; + + double f = force_multiplier * (desiredLen - len) / len; + + f = f * Math.pow(stretch, (getGraph().degree(v1) + getGraph().degree(v2) - 2)); + + // the actual movement distance 'dx' is the force multiplied by the + // distance to go. + double dx = f * vx; + double dy = f * vy; + SpringVertexData v1D, v2D; + v1D = springVertexData.getUnchecked(v1); + v2D = springVertexData.getUnchecked(v2); + + v1D.edgedx += dx; + v1D.edgedy += dy; + v2D.edgedx += -dx; + v2D.edgedy += -dy; + } + } catch(ConcurrentModificationException cme) { + relaxEdges(); + } + } + + protected void calculateRepulsion() { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + + SpringVertexData svd = springVertexData.getUnchecked(v); + if(svd == null) continue; + double dx = 0, dy = 0; + + for (V v2 : getGraph().getVertices()) { + if (v == v2) continue; + Point2D p = apply(v); + Point2D p2 = apply(v2); + if(p == null || p2 == null) continue; + double vx = p.getX() - p2.getX(); + double vy = p.getY() - p2.getY(); + double distanceSq = p.distanceSq(p2); + if (distanceSq == 0) { + dx += Math.random(); + dy += Math.random(); + } else if (distanceSq < repulsion_range_sq) { + double factor = 1; + dx += factor * vx / distanceSq; + dy += factor * vy / distanceSq; + } + } + double dlen = dx * dx + dy * dy; + if (dlen > 0) { + dlen = Math.sqrt(dlen) / 2; + svd.repulsiondx += dx / dlen; + svd.repulsiondy += dy / dlen; + } + } + } catch(ConcurrentModificationException cme) { + calculateRepulsion(); + } + } + + protected void moveNodes() + { + synchronized (getSize()) { + try { + for (V v : getGraph().getVertices()) { + if (isLocked(v)) continue; + SpringVertexData vd = springVertexData.getUnchecked(v); + if(vd == null) continue; + Point2D xyd = apply(v); + + vd.dx += vd.repulsiondx + vd.edgedx; + vd.dy += vd.repulsiondy + vd.edgedy; + + // keeps nodes from moving any faster than 5 per time unit + xyd.setLocation(xyd.getX()+Math.max(-5, Math.min(5, vd.dx)), + xyd.getY()+Math.max(-5, Math.min(5, vd.dy))); + + Dimension d = getSize(); + int width = d.width; + int height = d.height; + + if (xyd.getX() < 0) { + xyd.setLocation(0, xyd.getY()); + } else if (xyd.getX() > width) { + xyd.setLocation(width, xyd.getY()); + } + if (xyd.getY() < 0) { + xyd.setLocation(xyd.getX(), 0); + } else if (xyd.getY() > height) { + xyd.setLocation(xyd.getX(), height); + } + + } + } catch(ConcurrentModificationException cme) { + moveNodes(); + } + } + } + + protected static class SpringVertexData { + protected double edgedx; + protected double edgedy; + protected double repulsiondx; + protected double repulsiondy; + + /** movement speed, x */ + protected double dx; + + /** movement speed, y */ + protected double dy; + } + + + /** + * Used for changing the size of the layout in response to a component's size. + */ + public class SpringDimensionChecker extends ComponentAdapter { + @Override + public void componentResized(ComponentEvent e) { + setSize(e.getComponent().getSize()); + } + } + + /** + * @return true + */ + public boolean isIncremental() { + return true; + } + + /** + * @return false + */ + public boolean done() { + return false; + } + + /** + * No effect. + */ + public void reset() { + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/StaticLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Created on Jul 21, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + +/** + * StaticLayout places the vertices in the locations specified by its initializer, + * and has no other behavior. + * Vertex locations can be placed in a {@code Map} and then supplied to + * this layout as follows: {@code Function vertexLocations = Functions.forMap(map);} + * @author Tom Nelson - tomnelson@dev.java.net + */ +public class StaticLayout extends AbstractLayout { + + public StaticLayout(Graph graph, Function initializer, Dimension size) { + super(graph, initializer, size); + } + + public StaticLayout(Graph graph, Function initializer) { + super(graph, initializer); + } + + public StaticLayout(Graph graph) { + super(graph); + } + + public StaticLayout(Graph graph, Dimension size) { + super(graph, size); + } + + public void initialize() {} + + public void reset() {} +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/TreeLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 9, 2005 + */ + +package edu.uci.ics.jung.algorithms.layout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * @author Karlheinz Toni + * @author Tom Nelson - converted to jung2 + */ +public class TreeLayout implements Layout { + + protected Dimension size = new Dimension(600,600); + protected Forest graph; + protected Map basePositions = new HashMap(); + + protected LoadingCache locations = + CacheBuilder.newBuilder().build(new CacheLoader() { + public Point2D load(V vertex) { + return new Point2D.Double(); + } + }); + + protected transient Set alreadyDone = new HashSet(); + + /** + * The default horizontal vertex spacing. Initialized to 50. + */ + public static int DEFAULT_DISTX = 50; + + /** + * The default vertical vertex spacing. Initialized to 50. + */ + public static int DEFAULT_DISTY = 50; + + /** + * The horizontal vertex spacing. Defaults to {@code DEFAULT_XDIST}. + */ + protected int distX = 50; + + /** + * The vertical vertex spacing. Defaults to {@code DEFAULT_YDIST}. + */ + protected int distY = 50; + + protected transient Point m_currentPoint = new Point(); + + /** + * Creates an instance for the specified graph with default X and Y distances. + * @param g the graph on which the layout algorithm is to operate + */ + public TreeLayout(Forest g) { + this(g, DEFAULT_DISTX, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph and X distance with + * default Y distance. + * @param g the graph on which the layout algorithm is to operate + * @param distx the horizontal spacing between adjacent siblings + */ + public TreeLayout(Forest g, int distx) { + this(g, distx, DEFAULT_DISTY); + } + + /** + * Creates an instance for the specified graph, X distance, and Y distance. + * @param g the graph on which the layout algorithm is to operate + * @param distx the horizontal spacing between adjacent siblings + * @param disty the vertical spacing between adjacent siblings + */ + public TreeLayout(Forest g, int distx, int disty) { + if (g == null) + throw new IllegalArgumentException("Graph must be non-null"); + if (distx < 1 || disty < 1) + throw new IllegalArgumentException("X and Y distances must each be positive"); + this.graph = g; + this.distX = distx; + this.distY = disty; + buildTree(); + } + + protected void buildTree() { + this.m_currentPoint = new Point(0, 20); + Collection roots = TreeUtils.getRoots(graph); + if (roots.size() > 0 && graph != null) { + calculateDimensionX(roots); + for(V v : roots) { + calculateDimensionX(v); + m_currentPoint.x += this.basePositions.get(v)/2 + this.distX; + buildTree(v, this.m_currentPoint.x); + } + } + } + + protected void buildTree(V v, int x) { + + if (alreadyDone.add(v)) { + //go one level further down + this.m_currentPoint.y += this.distY; + this.m_currentPoint.x = x; + + this.setCurrentPositionFor(v); + + int sizeXofCurrent = basePositions.get(v); + + int lastX = x - sizeXofCurrent / 2; + + int sizeXofChild; + int startXofChild; + + for (V element : graph.getSuccessors(v)) { + sizeXofChild = this.basePositions.get(element); + startXofChild = lastX + sizeXofChild / 2; + buildTree(element, startXofChild); + lastX = lastX + sizeXofChild + distX; + } + this.m_currentPoint.y -= this.distY; + } + } + + private int calculateDimensionX(V v) { + + int size = 0; + int childrenNum = graph.getSuccessors(v).size(); + + if (childrenNum != 0) { + for (V element : graph.getSuccessors(v)) { + size += calculateDimensionX(element) + distX; + } + } + size = Math.max(0, size - distX); + basePositions.put(v, size); + + return size; + } + + private int calculateDimensionX(Collection roots) { + + int size = 0; + for(V v : roots) { + int childrenNum = graph.getSuccessors(v).size(); + + if (childrenNum != 0) { + for (V element : graph.getSuccessors(v)) { + size += calculateDimensionX(element) + distX; + } + } + size = Math.max(0, size - distX); + basePositions.put(v, size); + } + + return size; + } + + /** + * This method is not supported by this class. The size of the layout + * is determined by the topology of the tree, and by the horizontal + * and vertical spacing (optionally set by the constructor). + */ + public void setSize(Dimension size) { + throw new UnsupportedOperationException("Size of TreeLayout is set" + + " by vertex spacing in constructor"); + } + + protected void setCurrentPositionFor(V vertex) { + int x = m_currentPoint.x; + int y = m_currentPoint.y; + if(x < 0) size.width -= x; + + if(x > size.width-distX) + size.width = x + distX; + + if(y < 0) size.height -= y; + if(y > size.height-distY) + size.height = y + distY; + locations.getUnchecked(vertex).setLocation(m_currentPoint); + + } + + public Graph getGraph() { + return graph; + } + + public Dimension getSize() { + return size; + } + + public void initialize() { + + } + + public boolean isLocked(V v) { + return false; + } + + public void lock(V v, boolean state) { + } + + public void reset() { + } + + public void setGraph(Graph graph) { + if(graph instanceof Forest) { + this.graph = (Forest)graph; + buildTree(); + } else { + throw new IllegalArgumentException("graph must be a Forest"); + } + } + + public void setInitializer(Function initializer) { + } + + /** + * @return the center of this layout's area. + */ + public Point2D getCenter() { + return new Point2D.Double(size.getWidth()/2,size.getHeight()/2); + } + + public void setLocation(V v, Point2D location) { + locations.getUnchecked(v).setLocation(location); + } + + public Point2D apply(V v) { + return locations.getUnchecked(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + + + +Utility classes for updating layout positions. + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/RandomLocationTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Created on Jul 19, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.layout.util; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.util.Date; +import java.util.Random; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.StaticLayout; + +/** + * Provides a random vertex location within the bounds of the Dimension property. + * This provides a random location for unmapped vertices + * the first time they are accessed. + * + *

    Note: the generated values are not cached, so apply() will generate a new random + * location for the passed vertex every time it is called. If you want a consistent value, + * wrap this layout's generated values in a {@link StaticLayout} instance. + * + * @author Tom Nelson + * + * @param the vertex type + */ +public class RandomLocationTransformer implements Function { + Dimension d; + Random random; + + /** + * Creates an instance with the specified size which uses the current time + * as the random seed. + * @param d the size of the layout area + */ + public RandomLocationTransformer(Dimension d) { + this(d, new Date().getTime()); + } + + /** + * Creates an instance with the specified dimension and random seed. + * @param d the size of the layout area + * @param seed the seed for the internal random number generator + */ + public RandomLocationTransformer(final Dimension d, long seed) { + this.d = d; + this.random = new Random(seed); + } + + public Point2D apply(V v) { + return new Point2D.Double(random.nextDouble() * d.width, random.nextDouble() * d.height); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/Relaxer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,43 @@ +package edu.uci.ics.jung.algorithms.layout.util; + +/** + * Interface for operating the relax iterations on a layout. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public interface Relaxer { + + /** + * Execute a loop of steps in a new Thread, + * firing an event after each step. + */ + void relax(); + + /** + * Execute a loop of steps in the calling + * thread, firing no events. + */ + void prerelax(); + + /** + * Make the relaxer thread wait. + */ + void pause(); + + /** + * Make the relaxer thread resume. + * + */ + void resume(); + + /** + * Set flags to stop the relaxer thread. + */ + void stop(); + + /** + * @param i the sleep time between iterations, in milliseconds + */ + void setSleepTime(long i); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/layout/util/VisRunner.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.algorithms.layout.util; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; + +/** + * + * Implementation of a relaxer thread for layouts. + * Extracted from the {@code VisualizationModel} in previous + * versions of JUNG. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class VisRunner implements Relaxer, Runnable { + + protected boolean running; + protected IterativeContext process; + protected boolean stop; + protected boolean manualSuspend; + protected Thread thread; + + /** + * how long the relaxer thread pauses between iteration loops. + */ + protected long sleepTime = 100L; + + + /** + * Creates an instance for the specified process. + * @param process the process (generally a layout) for which this instance is created + */ + public VisRunner(IterativeContext process) { + this.process = process; + } + + /** + * @return the relaxerThreadSleepTime + */ + public long getSleepTime() { + return sleepTime; + } + + /** + * @param sleepTime the sleep time to set for this thread + */ + public void setSleepTime(long sleepTime) { + this.sleepTime = sleepTime; + } + + public void prerelax() { + manualSuspend = true; + long timeNow = System.currentTimeMillis(); + while (System.currentTimeMillis() - timeNow < 500 && !process.done()) { + process.step(); + } + manualSuspend = false; + } + + public void pause() { + manualSuspend = true; + } + + public void relax() { + // in case its running + stop(); + stop = false; + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.start(); + } + + /** + * Used for synchronization. + */ + public Object pauseObject = new String("PAUSE OBJECT"); + + public void resume() { + manualSuspend = false; + if(running == false) { + prerelax(); + relax(); + } else { + synchronized(pauseObject) { + pauseObject.notifyAll(); + } + } + } + + public synchronized void stop() { + if(thread != null) { + manualSuspend = false; + stop = true; + // interrupt the relaxer, in case it is paused or sleeping + // this should ensure that visRunnerIsRunning gets set to false + try { thread.interrupt(); } + catch(Exception ex) { + // the applet security manager may have prevented this. + // just sleep for a second to let the thread stop on its own + try { Thread.sleep(1000); } + catch(InterruptedException ie) {} // ignore + } + synchronized (pauseObject) { + pauseObject.notifyAll(); + } + } + } + + public void run() { + running = true; + try { + while (!process.done() && !stop) { + synchronized (pauseObject) { + while (manualSuspend && !stop) { + try { + pauseObject.wait(); + } catch (InterruptedException e) { + // ignore + } + } + } + process.step(); + + if (stop) + return; + + try { + Thread.sleep(sleepTime); + } catch (InterruptedException ie) { + // ignore + } + } + + } finally { + running = false; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/Metrics.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jun 7, 2008 + * + */ +package edu.uci.ics.jung.algorithms.metrics; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A class consisting of static methods for calculating graph metrics. + */ +public class Metrics +{ + /** + * Returns a Map of vertices to their clustering coefficients. + * The clustering coefficient cc(v) of a vertex v is defined as follows: + *

      + *
    • degree(v) == {0,1}: 0 + *
    • degree(v) == n, n >= 2: given S, the set of neighbors + * of v: cc(v) = (the sum over all w in S of the number of + * other elements of w that are neighbors of w) / ((|S| * (|S| - 1) / 2). + * Less formally, the fraction of v's neighbors that are also + * neighbors of each other. + *
    + *

    Note: This algorithm treats its argument as an undirected graph; + * edge direction is ignored. + * @param graph the graph whose clustering coefficients are to be calculated + * @param the vertex type + * @param the edge type + * @return the clustering coefficient for each vertex + * @see "The structure and function of complex networks, M.E.J. Newman, aps.arxiv.org/abs/cond-mat/0303516" + */ + public static Map clusteringCoefficients(Graph graph) + { + Map coefficients = new HashMap(); + + for (V v : graph.getVertices()) + { + int n = graph.getNeighborCount(v); + if (n < 2) + coefficients.put(v, new Double(0)); + else + { + // how many of v's neighbors are connected to each other? + ArrayList neighbors = new ArrayList(graph.getNeighbors(v)); + double edge_count = 0; + for (int i = 0; i < n; i++) + { + V w = neighbors.get(i); + for (int j = i+1; j < n; j++ ) + { + V x = neighbors.get(j); + edge_count += graph.isNeighbor(w, x) ? 1 : 0; + } + } + double possible_edges = (n * (n - 1))/2.0; + coefficients.put(v, new Double(edge_count / possible_edges)); + } + } + + return coefficients; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,26 @@ + + + + + + + +Specialized measures for graph properties. These currently include: + +

      +
    • StructuralHoles: calculates some of Burt's 'structural holes' +measures (e.g. efficiency, hierarchy, constraint). +
    • TriadicCensus: returns counts for each triad type found in a +graph. +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/StructuralHoles.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,343 @@ +/* + * Created on Sep 19, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.metrics; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + +/** + * Calculates some of the measures from Burt's text "Structural Holes: + * The Social Structure of Competition". + * + *

    Notes: + *

      + *
    • Each of these measures assumes that each edge has an associated + * non-null weight whose value is accessed through the specified + * Transformer instance. + *
    • Nonexistent edges are treated as edges with weight 0 for purposes + * of edge weight calculations. + *
    + * + *

    Based on code donated by Jasper Voskuilen and + * Diederik van Liere of the Department of Information and Decision Sciences + * at Erasmus University. + * + * @author Joshua O'Madadhain + * @author Jasper Voskuilen + * @see "Ronald Burt, Structural Holes: The Social Structure of Competition" + * @author Tom Nelson - converted to jung2 + */ +public class StructuralHoles { + + protected Function edge_weight; + protected Graph g; + + /** + * @param graph the graph for which the metrics are to be calculated + * @param nev the edge weights + */ + public StructuralHoles(Graph graph, Function nev) + { + this.g = graph; + this.edge_weight = nev; + } + + /** + * Burt's measure of the effective size of a vertex's network. Essentially, the + * number of neighbors minus the average degree of those in v's neighbor set, + * not counting ties to v. Formally: + *

    +     * effectiveSize(v) = v.degree() - (sum_{u in N(v)} sum_{w in N(u), w !=u,v} p(v,w)*m(u,w))
    +     * 
    + * where + *
      + *
    • N(a) = a.getNeighbors() + *
    • p(v,w) = normalized mutual edge weight of v and w + *
    • m(u,w) = maximum-scaled mutual edge weight of u and w + *
    + * @param v the vertex whose properties are being measured + * @return the effective size of the vertex's network + * + * @see #normalizedMutualEdgeWeight(Object, Object) + * @see #maxScaledMutualEdgeWeight(Object, Object) + */ + public double effectiveSize(V v) + { + double result = g.degree(v); + for(V u : g.getNeighbors(v)) { + + for(V w : g.getNeighbors(u)) { + + if (w != v && w != u) + result -= normalizedMutualEdgeWeight(v,w) * + maxScaledMutualEdgeWeight(u,w); + } + } + return result; + } + + /** + * Returns the effective size of v divided by the number of + * alters in v's network. (In other words, + * effectiveSize(v) / v.degree().) + * If v.degree() == 0, returns 0. + * + * @param v the vertex whose properties are being measured + * @return the effective size of the vertex divided by its degree + */ + public double efficiency(V v) { + double degree = g.degree(v); + + if (degree == 0) + return 0; + else + return effectiveSize(v) / degree; + } + + /** + * Burt's constraint measure (equation 2.4, page 55 of Burt, 1992). Essentially a + * measure of the extent to which v is invested in people who are invested in + * other of v's alters (neighbors). The "constraint" is characterized + * by a lack of primary holes around each neighbor. Formally: + *
    +     * constraint(v) = sum_{w in MP(v), w != v} localConstraint(v,w)
    +     * 
    + * where MP(v) is the subset of v's neighbors that are both predecessors and successors of v. + * @see #localConstraint(Object, Object) + * + * @param v the vertex whose properties are being measured + * @return the constraint of the vertex + */ + public double constraint(V v) { + double result = 0; + for(V w : g.getSuccessors(v)) { + + if (v != w && g.isPredecessor(v,w)) + { + result += localConstraint(v, w); + } + } + + return result; + } + + + /** + * Calculates the hierarchy value for a given vertex. Returns NaN when + * v's degree is 0, and 1 when v's degree is 1. + * Formally: + *
    +     * hierarchy(v) = (sum_{v in N(v), w != v} s(v,w) * log(s(v,w))}) / (v.degree() * Math.log(v.degree()) 
    +     * 
    + * where + *
      + *
    • N(v) = v.getNeighbors() + *
    • s(v,w) = localConstraint(v,w) / (aggregateConstraint(v) / v.degree()) + *
    + * @see #localConstraint(Object, Object) + * @see #aggregateConstraint(Object) + * + * @param v the vertex whose properties are being measured + * @return the hierarchy value for a given vertex + */ + public double hierarchy(V v) + { + double v_degree = g.degree(v); + + if (v_degree == 0) + return Double.NaN; + if (v_degree == 1) + return 1; + + double v_constraint = aggregateConstraint(v); + + double numerator = 0; + for (V w : g.getNeighbors(v)) { + + if (v != w) + { + double sl_constraint = localConstraint(v, w) / (v_constraint / v_degree); + numerator += sl_constraint * Math.log(sl_constraint); + } + } + + return numerator / (v_degree * Math.log(v_degree)); + } + + /** + * Returns the local constraint on v1 from a lack of primary holes + * around its neighbor v2. + * Based on Burt's equation 2.4. Formally: + *
    +     * localConstraint(v1, v2) = ( p(v1,v2) + ( sum_{w in N(v)} p(v1,w) * p(w, v2) ) )^2
    +     * 
    + * where + *
      + *
    • N(v) = v.getNeighbors() + *
    • p(v,w) = normalized mutual edge weight of v and w + *
    + * @param v1 the first vertex whose local constraint is desired + * @param v2 the second vertex whose local constraint is desired + * @return the local constraint on (v1, v2) + * @see #normalizedMutualEdgeWeight(Object, Object) + */ + public double localConstraint(V v1, V v2) + { + double nmew_vw = normalizedMutualEdgeWeight(v1, v2); + double inner_result = 0; + for (V w : g.getNeighbors(v1)) { + + inner_result += normalizedMutualEdgeWeight(v1,w) * + normalizedMutualEdgeWeight(w,v2); + } + return (nmew_vw + inner_result) * (nmew_vw + inner_result); + } + + /** + * The aggregate constraint on v. Based on Burt's equation 2.7. + * Formally: + *
    +     * aggregateConstraint(v) = sum_{w in N(v)} localConstraint(v,w) * O(w)
    +     * 
    + * where + *
      + *
    • N(v) = v.getNeighbors() + *
    • O(w) = organizationalMeasure(w) + *
    + * + * @param v the vertex whose properties are being measured + * @return the aggregate constraint on v + */ + public double aggregateConstraint(V v) + { + double result = 0; + for (V w : g.getNeighbors(v)) { + + result += localConstraint(v, w) * organizationalMeasure(g, w); + } + return result; + } + + /** + * A measure of the organization of individuals within the subgraph + * centered on v. Burt's text suggests that this is + * in some sense a measure of how "replaceable" v is by + * some other element of this subgraph. Should be a number in the + * closed interval [0,1]. + * + *

    This implementation returns 1. Users may wish to override this + * method in order to define their own behavior. + * @param g the subgraph centered on v + * @param v the vertex whose properties are being measured + * @return 1.0 (in this implementation) + */ + protected double organizationalMeasure(Graph g, V v) { + return 1.0; + } + + + /** + * Returns the proportion of v1's network time and energy invested + * in the relationship with v2. Formally: + *

    +     * normalizedMutualEdgeWeight(a,b) = mutual_weight(a,b) / (sum_c mutual_weight(a,c))
    +     * 
    + * Returns 0 if either numerator or denominator = 0, or if v1 == v2. + * @see #mutualWeight(Object, Object) + * @param v1 the first vertex of the pair whose property is being measured + * @param v2 the second vertex of the pair whose property is being measured + * @return the normalized mutual edge weight between v1 and v2 + */ + protected double normalizedMutualEdgeWeight(V v1, V v2) + { + if (v1 == v2) + return 0; + + double numerator = mutualWeight(v1, v2); + + if (numerator == 0) + return 0; + + double denominator = 0; + for (V v : g.getNeighbors(v1)) { + denominator += mutualWeight(v1, v); + } + if (denominator == 0) + return 0; + + return numerator / denominator; + } + + /** + * Returns the weight of the edge from v1 to v2 + * plus the weight of the edge from v2 to v1; + * if either edge does not exist, it is treated as an edge with weight 0. + * Undirected edges are treated as two antiparallel directed edges (that + * is, if there is one undirected edge with weight w connecting + * v1 to v2, the value returned is 2w). + * Ignores parallel edges; if there are any such, one is chosen at random. + * Throws NullPointerException if either edge is + * present but not assigned a weight by the constructor-specified + * NumberEdgeValue. + * + * @param v1 the first vertex of the pair whose property is being measured + * @param v2 the second vertex of the pair whose property is being measured + * @return the weights of the edges {@code} and {@code } + */ + protected double mutualWeight(V v1, V v2) + { + E e12 = g.findEdge(v1,v2); + E e21 = g.findEdge(v2,v1); + double w12 = (e12 != null ? edge_weight.apply(e12).doubleValue() : 0); + double w21 = (e21 != null ? edge_weight.apply(e21).doubleValue() : 0); + + return w12 + w21; + } + + /** + * The marginal strength of v1's relation with contact v2. + * Formally: + *
    +     * normalized_mutual_weight = mutual_weight(a,b) / (max_c mutual_weight(a,c))
    +     * 
    + * Returns 0 if either numerator or denominator is 0, or if v1 == v2. + * + * @param v1 the first vertex of the pair whose property is being measured + * @param v2 the second vertex of the pair whose property is being measured + * @return the marginal strength of v1's relation with v2 + * + * @see #mutualWeight(Object, Object) + */ + protected double maxScaledMutualEdgeWeight(V v1, V v2) + { + if (v1 == v2) + return 0; + + double numerator = mutualWeight(v1, v2); + + if (numerator == 0) + return 0; + + double denominator = 0; + for (V w : g.getNeighbors(v1)) { + + if (v2 != w) + denominator = Math.max(numerator, mutualWeight(v1, w)); + } + + if (denominator == 0) + return 0; + + return numerator / denominator; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/metrics/TriadicCensus.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.metrics; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; + + +/** + * TriadicCensus is a standard social network tool that counts, for each of the + * different possible configurations of three vertices, the number of times + * that that configuration occurs in the given graph. + * This may then be compared to the set of expected counts for this particular + * graph or to an expected sample. This is often used in p* modeling. + *

    + * To use this class, + *

    + * long[] triad_counts = TriadicCensus(dg);
    + * 
    + * where dg is a DirectedGraph. + * ith element of the array (for i in [1,16]) is the number of + * occurrences of the corresponding triad type. + * (The 0th element is not meaningful; this array is effectively 1-based.) + * To get the name of the ith triad (e.g. "003"), + * look at the global constant array c.TRIAD_NAMES[i] + *

    + * Triads are named as + * (number of pairs that are mutually tied) + * (number of pairs that are one-way tied) + * (number of non-tied pairs) + * in the triple. Since there are be only three pairs, there is a finite + * set of these possible triads. + *

    + * In fact, there are exactly 16, conventionally sorted by the number of + * realized edges in the triad: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Descriptions of the different types of triads
    Number Configuration Notes
    1003The empty triad
    2012
    3102
    4021D"Down": the directed edges point away
    5021U"Up": the directed edges meet
    6021C"Circle": one in, one out
    7111D"Down": 021D but one edge is mutual
    8111U"Up": 021U but one edge is mutual
    9030T"Transitive": two point to the same vertex
    10030C"Circle": A→B→C→A
    11201
    12120D"Down": 021D but the third edge is mutual
    13120U"Up": 021U but the third edge is mutual
    14120C"Circle": 021C but the third edge is mutual
    15210
    16300The complete
    + *

    + * This implementation takes O( m ), m is the number of edges in the graph. + *
    + * It is based on + * + * A subquadratic triad census algorithm for large sparse networks + * with small maximum degree + * Vladimir Batagelj and Andrej Mrvar, University of Ljubljana + * Published in Social Networks. + * @author Danyel Fisher + * @author Tom Nelson - converted to jung2 + * + */ +public class TriadicCensus { + + // NOTE THAT THIS RETURNS STANDARD 1-16 COUNT! + + // and their types + public static final String[] TRIAD_NAMES = { "N/A", "003", "012", "102", "021D", + "021U", "021C", "111D", "111U", "030T", "030C", "201", "120D", + "120U", "120C", "210", "300" }; + + public static final int MAX_TRIADS = TRIAD_NAMES.length; + + /** + * Returns an array whose ith element (for i in [1,16]) is the number of + * occurrences of the corresponding triad type in g. + * (The 0th element is not meaningful; this array is effectively 1-based.) + * + * @param g the graph whose properties are being measured + * @param the vertex type + * @param the edge type + * @return an array encoding the number of occurrences of each triad type + */ + public static long[] getCounts(DirectedGraph g) { + long[] count = new long[MAX_TRIADS]; + + List id = new ArrayList(g.getVertices()); + + // apply algorithm to each edge, one at at time + for (int i_v = 0; i_v < g.getVertexCount(); i_v++) { + V v = id.get(i_v); + for(V u : g.getNeighbors(v)) { + int triType = -1; + if (id.indexOf(u) <= i_v) + continue; + Set neighbors = new HashSet(g.getNeighbors(u)); + neighbors.addAll(g.getNeighbors(v)); + neighbors.remove(u); + neighbors.remove(v); + if (g.isSuccessor(v,u) && g.isSuccessor(u,v)) { + triType = 3; + } else { + triType = 2; + } + count[triType] += g.getVertexCount() - neighbors.size() - 2; + for (V w : neighbors) { + if (shouldCount(g, id, u, v, w)) { + count [ triType ( triCode(g, u, v, w) ) ] ++; + } + } + } + } + int sum = 0; + for (int i = 2; i <= 16; i++) { + sum += count[i]; + } + int n = g.getVertexCount(); + count[1] = n * (n-1) * (n-2) / 6 - sum; + return count; + } + + /** + * This is the core of the technique in the paper. Returns an int from 0 to + * 63 which encodes the presence of all possible links between u, v, and w + * as bit flags: WU = 32, UW = 16, WV = 8, VW = 4, UV = 2, VU = 1 + * + * @param g the graph for which the calculation is being made + * @param u a vertex in g + * @param v a vertex in g + * @param w a vertex in g + * @param the vertex type + * @param the edge type + * @return an int encoding the presence of all links between u, v, and w + */ + public static int triCode(Graph g, V u, V v, V w) { + int i = 0; + i += link(g, v, u ) ? 1 : 0; + i += link(g, u, v ) ? 2 : 0; + i += link(g, v, w ) ? 4 : 0; + i += link(g, w, v ) ? 8 : 0; + i += link(g, u, w ) ? 16 : 0; + i += link(g, w, u ) ? 32 : 0; + return i; + } + + protected static boolean link(Graph g, V a, V b) { + return g.isPredecessor(b, a); + } + + + /** + * @param triCode the code returned by {@code triCode()} + * @return the string code associated with the numeric type + */ + public static int triType( int triCode ) { + return codeToType[ triCode ]; + } + + /** + * For debugging purposes, this is copied straight out of the paper which + * means that they refer to triad types 1-16. + */ + protected static final int[] codeToType = { 1, 2, 2, 3, 2, 4, 6, 8, 2, 6, 5, 7, 3, 8, + 7, 11, 2, 6, 4, 8, 5, 9, 9, 13, 6, 10, 9, 14, 7, 14, 12, 15, 2, 5, + 6, 7, 6, 9, 10, 14, 4, 9, 9, 12, 8, 13, 14, 15, 3, 7, 8, 11, 7, 12, + 14, 15, 8, 14, 13, 15, 11, 15, 15, 16 }; + + /** + * Return true iff this ordering is canonical and therefore we should build statistics for it. + * + * @param g the graph whose properties are being examined + * @param id a list of the vertices in g; used to assign an index to each + * @param u a vertex in g + * @param v a vertex in g + * @param w a vertex in g + * @param the vertex type + * @param the edge type + * @return true if index(u) < index(w), or if index(v) < index(w) < index(u) + * and v doesn't link to w; false otherwise + */ + protected static boolean shouldCount(Graph g, List id, V u, V v, V w) { + int i_u = id.indexOf(u); + int i_w = id.indexOf(w); + if (i_u < i_w) + return true; + int i_v = id.indexOf(v); + if ((i_v < i_w) && (i_w < i_u) && (!g.isNeighbor(w,v))) + return true; + return false; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ + + + + + + + +

    Algorithms for graphs and networks. + +

    These algorithms are divided into categories as follows: +

      +
    • blockmodel: dividing graph elements (typically vertices) into +equivalence classes, +generally by topological properties (e.g. structural equivalence) +
    • cluster: identifying coherent (not necessarily disjoint) groups of elements +(e.g. weakly connected components, edge betweenness clustering) +
    • filters: removing parts of a graph according to specified criteria +
    • flows: calculating properties relating to network flows +(e.g. max flow/min cut) +
    • generators: creating graphs with certain properties +
    • importance (deprecated): assigning values to vertices/edges +based on topological properties +
    • layout: arrangement of graph elements, generally for visualization +
    • metrics: calculating structural properties (triad census, structural +holes) +
    • scoring: assigning values (denoting significance, influence, +centrality, etc.) to vertices/edges based on topological properties, +e.g. PageRank, HITS, betweenness centrality (replaces "importance", above) +
    • shortestpath: calculation of shortest paths between vertices +
    • util: low-level utility classes used in a variety of algorithms +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,370 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.DelegateToEdgeTransformer; +import edu.uci.ics.jung.algorithms.scoring.util.VEPair; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * An abstract class for algorithms that assign scores to vertices based on iterative methods. + * Generally, any (concrete) subclass will function by creating an instance, and then either calling + * evaluate (if the user wants to iterate until the algorithms is 'done') or + * repeatedly call step (if the user wants to observe the values at each step). + */ +public abstract class AbstractIterativeScorer implements IterativeContext, VertexScorer +{ + /** + * Maximum number of iterations to use before terminating. Defaults to 100. + */ + protected int max_iterations; + + /** + * Minimum change from one step to the next; if all changes are ≤ tolerance, + * no further updates will occur. + * Defaults to 0.001. + */ + protected double tolerance; + + /** + * The graph on which the calculations are to be made. + */ + protected Hypergraph graph; + + /** + * The total number of iterations used so far. + */ + protected int total_iterations; + + /** + * The edge weights used by this algorithm. + */ + protected Function, ? extends Number> edge_weights; + + /** + * Indicates whether the output and current values are in a 'swapped' state. + * Intended for internal use only. + */ + protected boolean output_reversed; + + /** + * The map in which the output values are stored. + */ + private Map output; + + /** + * The map in which the current values are stored. + */ + private Map current_values; + + /** + * A flag representing whether this instance tolerates disconnected graphs. + * Instances that do not accept disconnected graphs may have unexpected behavior + * on disconnected graphs; they are not guaranteed to do an explicit check. + * Defaults to true. + */ + private boolean accept_disconnected_graph; + + + protected boolean hyperedges_are_self_loops = false; + + /** + * Sets the output value for this vertex. + * @param v the vertex whose output value is to be set + * @param value the value to set + */ + protected void setOutputValue(V v, T value) + { + output.put(v, value); + } + + /** + * Gets the output value for this vertex. + * @param v the vertex whose output value is to be retrieved + * @return the output value for this vertex + */ + protected T getOutputValue(V v) + { + return output.get(v); + } + + /** + * Gets the current value for this vertex + * @param v the vertex whose current value is to be retrieved + * @return the current value for this vertex + */ + protected T getCurrentValue(V v) + { + return current_values.get(v); + } + + /** + * Sets the current value for this vertex. + * @param v the vertex whose current value is to be set + * @param value the current value to set + */ + protected void setCurrentValue(V v, T value) + { + current_values.put(v, value); + } + + /** + * The largest change seen so far among all vertex scores. + */ + protected double max_delta; + + /** + * Creates an instance for the specified graph and edge weights. + * @param g the graph for which the instance is to be created + * @param edge_weights the edge weights for this instance + */ + public AbstractIterativeScorer(Hypergraph g, + Function edge_weights) + { + this.graph = g; + this.max_iterations = 100; + this.tolerance = 0.001; + this.accept_disconnected_graph = true; + setEdgeWeights(edge_weights); + } + + /** + * Creates an instance for the specified graph g. + * NOTE: This constructor does not set the internal + * edge_weights variable. If this variable is used by + * the subclass which invoked this constructor, it must be initialized + * by that subclass. + * @param g the graph for which the instance is to be created + */ + public AbstractIterativeScorer(Hypergraph g) + { + this.graph = g; + this.max_iterations = 100; + this.tolerance = 0.001; + this.accept_disconnected_graph = true; + } + + /** + * Initializes the internal state for this instance. + */ + protected void initialize() + { + this.total_iterations = 0; + this.max_delta = Double.MIN_VALUE; + this.output_reversed = true; + this.current_values = new HashMap(); + this.output = new HashMap(); + } + + /** + * Steps through this scoring algorithm until a termination condition is reached. + */ + public void evaluate() + { + do + step(); + while (!done()); + } + + /** + * Returns true if the total number of iterations is greater than or equal to + * max_iterations + * or if the maximum value change observed is less than tolerance. + */ + public boolean done() + { + return total_iterations >= max_iterations || max_delta < tolerance; + } + + /** + * Performs one step of this algorithm; updates the state (value) for each vertex. + */ + public void step() + { + swapOutputForCurrent(); + + for (V v : graph.getVertices()) + { + double diff = update(v); + updateMaxDelta(v, diff); + } + total_iterations++; + afterStep(); + } + + /** + * + */ + protected void swapOutputForCurrent() + { + Map tmp = output; + output = current_values; + current_values = tmp; + output_reversed = !output_reversed; + } + + /** + * Updates the value for v. + * @param v the vertex whose value is to be updated + * @return the updated value + */ + protected abstract double update(V v); + + protected void updateMaxDelta(V v, double diff) + { + max_delta = Math.max(max_delta, diff); + } + + protected void afterStep() {} + + public T getVertexScore(V v) + { + if (!graph.containsVertex(v)) + throw new IllegalArgumentException("Vertex " + v + " not an element of this graph"); + + return output.get(v); + } + + /** + * Returns the maximum number of iterations that this instance will use. + * @return the maximum number of iterations that evaluate will use + * prior to terminating + */ + public int getMaxIterations() + { + return max_iterations; + } + + /** + * Returns the number of iterations that this instance has used so far. + * @return the number of iterations that this instance has used so far + */ + public int getIterations() + { + return total_iterations; + } + + /** + * Sets the maximum number of times that evaluate will call step. + * @param max_iterations the maximum + */ + public void setMaxIterations(int max_iterations) + { + this.max_iterations = max_iterations; + } + + /** + * Gets the size of the largest change (difference between the current and previous values) + * for any vertex that can be tolerated. Once all changes are less than this value, + * evaluate will terminate. + * @return the size of the largest change that evaluate() will permit + */ + public double getTolerance() + { + return tolerance; + } + + /** + * Sets the size of the largest change (difference between the current and previous values) + * for any vertex that can be tolerated. + * @param tolerance the size of the largest change that evaluate() will permit + */ + public void setTolerance(double tolerance) + { + this.tolerance = tolerance; + } + + /** + * Returns the Function that this instance uses to associate edge weights with each edge. + * @return the Function that associates an edge weight with each edge + */ + public Function, ? extends Number> getEdgeWeights() + { + return edge_weights; + } + + /** + * Sets the Function that this instance uses to associate edge weights with each edge + * @param edge_weights the Function to use to associate an edge weight with each edge + * @see edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight + */ + public void setEdgeWeights(Function edge_weights) + { + this.edge_weights = new DelegateToEdgeTransformer(edge_weights); + } + + /** + * Gets the edge weight for e in the context of its (incident) vertex v. + * @param v the vertex incident to e as a context in which the edge weight is to be calculated + * @param e the edge whose weight is to be returned + * @return the edge weight for e in the context of its (incident) vertex v + */ + protected Number getEdgeWeight(V v, E e) + { + return edge_weights.apply(new VEPair(v,e)); + } + + /** + * Collects the 'potential' from v (its current value) if it has no outgoing edges; this + * can then be redistributed among the other vertices as a means of normalization. + * @param v the vertex whose potential is being collected + */ + protected void collectDisappearingPotential(V v) {} + + /** + * Specifies whether this instance should accept vertices with no outgoing edges. + * @param accept true if this instance should accept vertices with no outgoing edges, false otherwise + */ + public void acceptDisconnectedGraph(boolean accept) + { + this.accept_disconnected_graph = accept; + } + + /** + * Returns true if this instance accepts vertices with no outgoing edges, and false otherwise. + * @return true if this instance accepts vertices with no outgoing edges, otherwise false + */ + public boolean isDisconnectedGraphOK() + { + return this.accept_disconnected_graph; + } + + /** + * Specifies whether hyperedges are to be treated as self-loops. If they + * are, then potential will flow along a hyperedge a vertex to itself, + * just as it does to all other vertices incident to that hyperedge. + * @param arg if {@code true}, hyperedges are treated as self-loops + */ + public void setHyperedgesAreSelfLoops(boolean arg) + { + this.hyperedges_are_self_loops = arg; + } + + /** + * Returns the effective number of vertices incident to this edge. If + * the graph is a binary relation or if hyperedges are treated as self-loops, + * the value returned is {@code graph.getIncidentCount(e)}; otherwise it is + * {@code graph.getIncidentCount(e) - 1}. + * @param e the edge whose incident edge count is requested + * @return the edge count, adjusted based on how hyperedges are treated + */ + protected int getAdjustedIncidentCount(E e) + { + return graph.getIncidentCount(e) - (hyperedges_are_self_loops ? 0 : 1); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/AbstractIterativeScorerWithPriors.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Created on Jul 14, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * An abstract class for iterative random-walk-based vertex scoring algorithms + * that have a + * fixed probability, for each vertex, of 'jumping' to that vertex at each + * step in the algorithm (rather than following a link out of that vertex). + * + * @param the vertex type + * @param the edge type + * @param the score type + */ +public abstract class AbstractIterativeScorerWithPriors extends + AbstractIterativeScorer implements VertexScorer +{ + /** + * The prior probability of each vertex being visited on a given + * 'jump' (non-link-following) step. + */ + protected Function vertex_priors; + + /** + * The probability of making a 'jump' at each step. + */ + protected double alpha; + + /** + * Creates an instance for the specified graph, edge weights, vertex + * priors, and jump probability. + * @param g the graph whose vertices are to be assigned scores + * @param edge_weights the edge weights to use in the score assignment + * @param vertex_priors the prior probabilities of each vertex being 'jumped' to + * @param alpha the probability of making a 'jump' at each step + */ + public AbstractIterativeScorerWithPriors(Hypergraph g, + Function edge_weights, + Function vertex_priors, double alpha) + { + super(g, edge_weights); + this.vertex_priors = vertex_priors; + this.alpha = alpha; + initialize(); + } + + /** + * Creates an instance for the specified graph, vertex priors, and jump + * probability, with edge weights specified by the subclass. + * @param g the graph whose vertices are to be assigned scores + * @param vertex_priors the prior probabilities of each vertex being 'jumped' to + * @param alpha the probability of making a 'jump' at each step + */ + public AbstractIterativeScorerWithPriors(Hypergraph g, + Function vertex_priors, double alpha) + { + super(g); + this.vertex_priors = vertex_priors; + this.alpha = alpha; + initialize(); + } + + /** + * Initializes the state of this instance. + */ + @Override + public void initialize() + { + super.initialize(); + // initialize output values to priors + // (output and current are swapped before each step(), so current will + // have priors when update()s start happening) + for (V v : graph.getVertices()) + setOutputValue(v, getVertexPrior(v)); + } + + /** + * Returns the prior probability for v. + * @param v the vertex whose prior probability is being queried + * @return the prior probability for v + */ + protected S getVertexPrior(V v) + { + return vertex_priors.apply(v); + } + + /** + * Returns a Function which maps each vertex to its prior probability. + * @return a Function which maps each vertex to its prior probability + */ + public Function getVertexPriors() + { + return vertex_priors; + } + + /** + * Returns the probability of making a 'jump' (non-link-following step). + * @return the probability of making a 'jump' (non-link-following step) + */ + public double getAlpha() + { + return alpha; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BarycenterScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex according to the sum of its distances to all other vertices. + */ +public class BarycenterScorer extends DistanceCentralityScorer +{ + /** + * Creates an instance with the specified graph and distance metric. + * @param graph the input graph + * @param distance the distance metric to use + */ + public BarycenterScorer(Hypergraph graph, Distance distance) + { + super(graph, distance, false); + } + + /** + * Creates an instance with the specified graph and edge weights. + * Will generate a Distance metric internally based on the edge weights. + * @param graph the input graph + * @param edge_weights the edge weights to use to calculate vertex/vertex distances + */ + public BarycenterScorer(Hypergraph graph, Function edge_weights) + { + super(graph, edge_weights, false); + } + + /** + * Creates an instance with the specified graph. + * Will generate a Distance metric internally assuming that the + * graph is unweighted. + * @param graph the input graph + */ + public BarycenterScorer(Hypergraph graph) + { + super(graph, false); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/BetweennessCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,350 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Sep 16, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Stack; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.util.MapBinaryHeap; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; + +/** + * Computes betweenness centrality for each vertex and edge in the graph. + * + * @see "Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. Journal of Mathematical Sociology 25(2):163-177, 2001." + */ +public class BetweennessCentrality + implements VertexScorer, EdgeScorer +{ + protected Graph graph; + protected Map vertex_scores; + protected Map edge_scores; + protected Map vertex_data; + + /** + * Calculates betweenness scores based on the all-pairs unweighted shortest paths + * in the graph. + * @param graph the graph for which the scores are to be calculated + */ + public BetweennessCentrality(Graph graph) + { + initialize(graph); + computeBetweenness(new LinkedList(), Functions.constant(1)); + } + + /** + * Calculates betweenness scores based on the all-pairs weighted shortest paths in the + * graph. + * + *

    NOTE: This version of the algorithm may not work correctly on all graphs; we're still + * working out the bugs. Use at your own risk. + * @param graph the graph for which the scores are to be calculated + * @param edge_weights the edge weights to be used in the path length calculations + */ + public BetweennessCentrality(Graph graph, + Function edge_weights) + { + // reject negative-weight edges up front + for (E e : graph.getEdges()) + { + double e_weight = edge_weights.apply(e).doubleValue(); + if (e_weight < 0) + throw new IllegalArgumentException(String.format( + "Weight for edge '%s' is < 0: %d", e, e_weight)); + } + + initialize(graph); + computeBetweenness(new MapBinaryHeap(new BetweennessComparator()), + edge_weights); + } + + protected void initialize(Graph graph) + { + this.graph = graph; + this.vertex_scores = new HashMap(); + this.edge_scores = new HashMap(); + this.vertex_data = new HashMap(); + + for (V v : graph.getVertices()) + this.vertex_scores.put(v, 0.0); + + for (E e : graph.getEdges()) + this.edge_scores.put(e, 0.0); + } + + protected void computeBetweenness(Queue queue, + Function edge_weights) + { + for (V v : graph.getVertices()) + { + // initialize the betweenness data for this new vertex + for (V s : graph.getVertices()) + this.vertex_data.put(s, new BetweennessData()); + +// if (v.equals(new Integer(0))) +// System.out.println("pause"); + + vertex_data.get(v).numSPs = 1; + vertex_data.get(v).distance = 0; + + Stack stack = new Stack(); +// Buffer queue = new UnboundedFifoBuffer(); +// queue.add(v); + queue.offer(v); + + while (!queue.isEmpty()) + { +// V w = queue.remove(); + V w = queue.poll(); + stack.push(w); + BetweennessData w_data = vertex_data.get(w); + + for (E e : graph.getOutEdges(w)) + { + // TODO (jrtom): change this to getOtherVertices(w, e) + V x = graph.getOpposite(w, e); + if (x.equals(w)) + continue; + double wx_weight = edge_weights.apply(e).doubleValue(); + + +// for(V x : graph.getSuccessors(w)) +// { +// if (x.equals(w)) +// continue; + + // FIXME: the other problem is that I need to + // keep putting the neighbors of things we've just + // discovered in the queue, if they're undiscovered or + // at greater distance. + + // FIXME: this is the problem, right here, I think: + // need to update position in queue if distance changes + // (which can only happen with weighted edges). + // for each outgoing edge e from w, get other end x + // if x not already visited (dist x < 0) + // set x's distance to w's dist + edge weight + // add x to queue; pri in queue is x's dist + // if w's dist + edge weight < x's dist + // update x's dist + // update x in queue (MapBinaryHeap) + // clear x's incoming edge list + // if w's dist + edge weight = x's dist + // add e to x's incoming edge list + + BetweennessData x_data = vertex_data.get(x); + double x_potential_dist = w_data.distance + wx_weight; + + if (x_data.distance < 0) + { +// queue.add(x); +// vertex_data.get(x).distance = vertex_data.get(w).distance + 1; + x_data.distance = x_potential_dist; + queue.offer(x); + } + + // note: + // (1) this can only happen with weighted edges + // (2) x's SP count and incoming edges are updated below + if (x_data.distance > x_potential_dist) + { + x_data.distance = x_potential_dist; + // invalidate previously identified incoming edges + // (we have a new shortest path distance to x) + x_data.incomingEdges.clear(); + // update x's position in queue + ((MapBinaryHeap)queue).update(x); + } +// if (vertex_data.get(x).distance == vertex_data.get(w).distance + 1) + // +// if (x_data.distance == x_potential_dist) +// { +// x_data.numSPs += w_data.numSPs; +//// vertex_data.get(x).predecessors.add(w); +// x_data.incomingEdges.add(e); +// } + } + for (E e: graph.getOutEdges(w)) + { + V x = graph.getOpposite(w, e); + if (x.equals(w)) + continue; + double e_weight = edge_weights.apply(e).doubleValue(); + BetweennessData x_data = vertex_data.get(x); + double x_potential_dist = w_data.distance + e_weight; + if (x_data.distance == x_potential_dist) + { + x_data.numSPs += w_data.numSPs; +// vertex_data.get(x).predecessors.add(w); + x_data.incomingEdges.add(e); + } + } + } + while (!stack.isEmpty()) + { + V x = stack.pop(); + +// for (V w : vertex_data.get(x).predecessors) + for (E e : vertex_data.get(x).incomingEdges) + { + V w = graph.getOpposite(x, e); + double partialDependency = + vertex_data.get(w).numSPs / vertex_data.get(x).numSPs * + (1.0 + vertex_data.get(x).dependency); + vertex_data.get(w).dependency += partialDependency; +// E w_x = graph.findEdge(w, x); +// double w_x_score = edge_scores.get(w_x).doubleValue(); +// w_x_score += partialDependency; +// edge_scores.put(w_x, w_x_score); + double e_score = edge_scores.get(e).doubleValue(); + edge_scores.put(e, e_score + partialDependency); + } + if (!x.equals(v)) + { + double x_score = vertex_scores.get(x).doubleValue(); + x_score += vertex_data.get(x).dependency; + vertex_scores.put(x, x_score); + } + } + } + + if(graph instanceof UndirectedGraph) + { + for (V v : graph.getVertices()) { + double v_score = vertex_scores.get(v).doubleValue(); + v_score /= 2.0; + vertex_scores.put(v, v_score); + } + for (E e : graph.getEdges()) { + double e_score = edge_scores.get(e).doubleValue(); + e_score /= 2.0; + edge_scores.put(e, e_score); + } + } + + vertex_data.clear(); + } + +// protected void computeWeightedBetweenness(Function edge_weights) +// { +// for (V v : graph.getVertices()) +// { +// // initialize the betweenness data for this new vertex +// for (V s : graph.getVertices()) +// this.vertex_data.put(s, new BetweennessData()); +// vertex_data.get(v).numSPs = 1; +// vertex_data.get(v).distance = 0; +// +// Stack stack = new Stack(); +//// Buffer queue = new UnboundedFifoBuffer(); +// SortedSet pqueue = new TreeSet(new BetweennessComparator()); +//// queue.add(v); +// pqueue.add(v); +// +//// while (!queue.isEmpty()) +// while (!pqueue.isEmpty()) +// { +//// V w = queue.remove(); +// V w = pqueue.first(); +// pqueue.remove(w); +// stack.push(w); +// +//// for(V x : graph.getSuccessors(w)) +// for (E e : graph.getOutEdges(w)) +// { +// // TODO (jrtom): change this to getOtherVertices(w, e) +// V x = graph.getOpposite(w, e); +// if (x.equals(w)) +// continue; +// double e_weight = edge_weights.transform(e).doubleValue(); +// +// if (vertex_data.get(x).distance < 0) +// { +//// queue.add(x); +// pqueue.add(v); +//// vertex_data.get(x).distance = vertex_data.get(w).distance + 1; +// vertex_data.get(x).distance = +// vertex_data.get(w).distance + e_weight; +// } +// +//// if (vertex_data.get(x).distance == vertex_data.get(w).distance + 1) +// if (vertex_data.get(x).distance == +// vertex_data.get(w).distance + e_weight) +// { +// vertex_data.get(x).numSPs += vertex_data.get(w).numSPs; +// vertex_data.get(x).predecessors.add(w); +// } +// } +// } +// updateScores(v, stack); +// } +// +// if(graph instanceof UndirectedGraph) +// adjustUndirectedScores(); +// +// vertex_data.clear(); +// } + + public Double getVertexScore(V v) + { + return vertex_scores.get(v); + } + + public Double getEdgeScore(E e) + { + return edge_scores.get(e); + } + + private class BetweennessData + { + double distance; + double numSPs; +// List predecessors; + List incomingEdges; + double dependency; + + BetweennessData() + { + distance = -1; + numSPs = 0; +// predecessors = new ArrayList(); + incomingEdges = new ArrayList(); + dependency = 0; + } + + @Override + public String toString() + { + return "[d:" + distance + ", sp:" + numSPs + + ", p:" + incomingEdges + ", d:" + dependency + "]\n"; +// ", p:" + predecessors + ", d:" + dependency + "]\n"; + } + } + + private class BetweennessComparator implements Comparator + { + public int compare(V v1, V v2) + { + return vertex_data.get(v1).distance > vertex_data.get(v2).distance ? 1 : -1; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/ClosenessCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex based on the mean distance to each other vertex. + * + * @author Joshua O'Madadhain + */ +public class ClosenessCentrality extends DistanceCentralityScorer +{ + + /** + * Creates an instance using the specified vertex/vertex distance metric. + * @param graph the input + * @param distance the vertex/vertex distance metric. + */ + public ClosenessCentrality(Hypergraph graph, Distance distance) + { + super(graph, distance, true); + } + + /** + * Creates an instance which measures distance using the specified edge weights. + * @param graph the input graph + * @param edge_weights the edge weights to be used to determine vertex/vertex distances + */ + public ClosenessCentrality(Hypergraph graph, Function edge_weights) + { + super(graph, edge_weights, true); + } + + /** + * Creates an instance which measures distance on the graph without edge weights. + * @param graph the graph whose vertices' centrality scores will be calculated + */ + public ClosenessCentrality(Hypergraph graph) + { + super(graph, true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DegreeScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns a score to each vertex equal to its degree. + * + * @param the vertex type + */ +public class DegreeScorer implements VertexScorer +{ + /** + * The graph for which scores are to be generated. + */ + protected Hypergraph graph; + + /** + * Creates an instance for the specified graph. + * @param graph the input graph + */ + public DegreeScorer(Hypergraph graph) + { + this.graph = graph; + } + + /** + * Returns the degree of the vertex. + * @return the degree of the vertex + */ + public Integer getVertexScore(V v) + { + return graph.degree(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/DistanceCentralityScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * Created on Jul 10, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance; +import edu.uci.ics.jung.algorithms.shortestpath.Distance; +import edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to vertices based on their distances to each other vertex + * in the graph. + * + * This class optionally normalizes its results based on the value of its + * 'averaging' constructor parameter. If it is true, + * then the value returned for vertex v is 1 / (_average_ distance from v to all other vertices); + * this is sometimes called closeness centrality. + * If it is false, then the value returned is 1 / (_total_ distance from + * v to all other vertices); this is sometimes referred to as barycenter centrality. + * (If the average/total distance is 0, the value returned is {@code Double.POSITIVE_INFINITY}.) + * + * @see BarycenterScorer + * @see ClosenessCentrality + */ +public class DistanceCentralityScorer implements VertexScorer +{ + /** + * The graph on which the vertex scores are to be calculated. + */ + protected Hypergraph graph; + + /** + * The metric to use for specifying the distance between pairs of vertices. + */ + protected Distance distance; + + /** + * The cache for the output results. Null encodes "not yet calculated", + * < 0 encodes "no such distance exists". + */ + protected Map output; + + /** + * Specifies whether the values returned are the sum of the v-distances + * or the mean v-distance. + */ + protected boolean averaging; + + /** + * Specifies whether, for a vertex v with missing (null) distances, + * v's score should ignore the missing values or be set to 'null'. + * Defaults to 'true'. + */ + protected boolean ignore_missing; + + /** + * Specifies whether the values returned should ignore self-distances + * (distances from v to itself). + * Defaults to 'true'. + */ + protected boolean ignore_self_distances; + + /** + * Creates an instance with the specified graph, distance metric, and + * averaging behavior. + * + * @param graph The graph on which the vertex scores are to be calculated. + * @param distance The metric to use for specifying the distance between + * pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of all + * v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, Distance distance, + boolean averaging, boolean ignore_missing, + boolean ignore_self_distances) + { + this.graph = graph; + this.distance = distance; + this.averaging = averaging; + this.ignore_missing = ignore_missing; + this.ignore_self_distances = ignore_self_distances; + this.output = new HashMap(); + } + + /** + * Equivalent to this(graph, distance, averaging, true, true). + * + * @param graph The graph on which the vertex scores are to be calculated. + * @param distance The metric to use for specifying the distance between + * pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of all + * v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, Distance distance, + boolean averaging) + { + this(graph, distance, averaging, true, true); + } + + /** + * Creates an instance with the specified graph and averaging behavior + * whose vertex distances are calculated based on the specified edge + * weights. + * + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param edge_weights The edge weights to use for specifying the distance + * between pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, + Function edge_weights, boolean averaging, + boolean ignore_missing, boolean ignore_self_distances) + { + this(graph, new DijkstraDistance(graph, edge_weights), averaging, + ignore_missing, ignore_self_distances); + } + + /** + * Equivalent to this(graph, edge_weights, averaging, true, true). + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param edge_weights The edge weights to use for specifying the distance + * between pairs of vertices. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, + Function edge_weights, boolean averaging) + { + this(graph, new DijkstraDistance(graph, edge_weights), averaging, + true, true); + } + + /** + * Creates an instance with the specified graph and averaging behavior + * whose vertex distances are calculated on the unweighted graph. + * + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + * @param ignore_missing Specifies whether scores for missing distances + * are to ignore missing distances or be set to null. + * @param ignore_self_distances Specifies whether distances from a vertex + * to itself should be included in its score. + */ + public DistanceCentralityScorer(Hypergraph graph, boolean averaging, + boolean ignore_missing, boolean ignore_self_distances) + { + this(graph, new UnweightedShortestPath(graph), averaging, + ignore_missing, ignore_self_distances); + } + + /** + * Equivalent to this(graph, averaging, true, true). + * @param graph The graph on which the vertex scores are to be + * calculated. + * @param averaging Specifies whether the values returned is the sum of + * all v-distances or the mean v-distance. + */ + public DistanceCentralityScorer(Hypergraph graph, boolean averaging) + { + this(graph, new UnweightedShortestPath(graph), averaging, true, true); + } + + /** + * Calculates the score for the specified vertex. Returns {@code null} if + * there are missing distances and such are not ignored by this instance. + */ + public Double getVertexScore(V v) + { + Double value = output.get(v); + if (value != null) + { + if (value < 0) + return null; + return value; + } + + Map v_distances = new HashMap(distance.getDistanceMap(v)); + if (ignore_self_distances) + v_distances.remove(v); + + // if we don't ignore missing distances and there aren't enough + // distances, output null (shortcut) + if (!ignore_missing) + { + int num_dests = graph.getVertexCount() - + (ignore_self_distances ? 1 : 0); + if (v_distances.size() != num_dests) + { + output.put(v, -1.0); + return null; + } + } + + Double sum = 0.0; + for (V w : graph.getVertices()) + { + if (w.equals(v) && ignore_self_distances) + continue; + Number w_distance = v_distances.get(w); + if (w_distance == null) + if (ignore_missing) + continue; + else + { + output.put(v, -1.0); + return null; + } + else + sum += w_distance.doubleValue(); + } + value = sum; + if (averaging) + value /= v_distances.size(); + + double score = value == 0 ? + Double.POSITIVE_INFINITY : + 1.0 / value; + output.put(v, score); + + return score; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EdgeScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + + +/** + * An interface for algorithms that assign scores to edges. + * + * @param the edge type + * @param the score type + */ +public interface EdgeScorer +{ + /** + * @param e the edge whose score is requested + * @return the algorithm's score for this edge + */ + public S getEdgeScore(E e); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/EigenvectorCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Calculates eigenvector centrality for each vertex in the graph. + * The 'eigenvector centrality' for a vertex is defined as the fraction of + * time that a random walk(er) will spend at that vertex over an infinite + * time horizon. + * Assumes that the graph is strongly connected. + */ +public class EigenvectorCentrality extends PageRank +{ + /** + * Creates an instance with the specified graph and edge weights. + * The outgoing edge weights for each edge must sum to 1. + * (See UniformDegreeWeight for one way to handle this for + * undirected graphs.) + * @param graph the graph for which the centrality is to be calculated + * @param edge_weights the edge weights + */ + public EigenvectorCentrality(Hypergraph graph, + Function edge_weights) + { + super(graph, edge_weights, 0); + acceptDisconnectedGraph(false); + } + + /** + * Creates an instance with the specified graph and default edge weights. + * (Default edge weights: UniformDegreeWeight.) + * @param graph the graph for which the centrality is to be calculated. + */ + public EigenvectorCentrality(Hypergraph graph) + { + super(graph, 0); + acceptDisconnectedGraph(false); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITS.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Created on Jul 15, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Graph; + +/** + * Assigns hub and authority scores to each vertex depending on the topology of + * the network. The essential idea is that a vertex is a hub to the extent + * that it links to authoritative vertices, and is an authority to the extent + * that it links to 'hub' vertices. + * + *

    The classic HITS algorithm essentially proceeds as follows: + *

    + * assign equal initial hub and authority values to each vertex
    + * repeat
    + *   for each vertex w:
    + *     w.hub = sum over successors x of x.authority
    + *     w.authority = sum over predecessors v of v.hub
    + *   normalize hub and authority scores so that the sum of the squares of each = 1
    + * until scores converge
    + * 
    + * + * HITS is somewhat different from random walk/eigenvector-based algorithms + * such as PageRank in that: + *
      + *
    • there are two mutually recursive scores being calculated, rather than + * a single value + *
    • the edge weights are effectively all 1, i.e., they can't be interpreted + * as transition probabilities. This means that the more inlinks and outlinks + * that a vertex has, the better, since adding an inlink (or outlink) does + * not dilute the influence of the other inlinks (or outlinks) as in + * random walk-based algorithms. + *
    • the scores cannot be interpreted as posterior probabilities (due to the different + * normalization) + *
    + * + * This implementation has the classic behavior by default. However, it has + * been generalized somewhat so that it can act in a more "PageRank-like" fashion: + *
      + *
    • this implementation has an optional 'random jump probability' parameter analogous + * to the 'alpha' parameter used by PageRank. Varying this value between 0 and 1 + * allows the user to vary between the classic HITS behavior and one in which the + * scores are smoothed to a uniform distribution. + * The default value for this parameter is 0 (no random jumps possible). + *
    • the edge weights can be set to anything the user likes, and in + * particular they can be set up (e.g. using UniformDegreeWeight) + * so that the weights of the relevant edges incident to a vertex sum to 1. + *
    • The vertex score normalization has been factored into its own method + * so that it can be overridden by a subclass. Thus, for example, + * since the vertices' values are set to sum to 1 initially, if the weights of the + * relevant edges incident to a vertex sum to 1, then the vertices' values + * will continue to sum to 1 if the "sum-of-squares" normalization code + * is overridden to a no-op. (Other normalization methods may also be employed.) + *
    + * + * @param the vertex type + * @param the edge type + * + * @see "'Authoritative sources in a hyperlinked environment' by Jon Kleinberg, 1997" + */ +public class HITS extends HITSWithPriors +{ + + /** + * Creates an instance for the specified graph, edge weights, and alpha + * (random jump probability) parameter. + * @param g the input graph + * @param edge_weights the weights to use for each edge + * @param alpha the probability of a hub giving some authority to all vertices, + * and of an authority increasing the score of all hubs (not just those connected + * via links) + */ + public HITS(Graph g, Function edge_weights, double alpha) + { + super(g, edge_weights, ScoringUtils.getHITSUniformRootPrior(g.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph and alpha (random jump probability) + * parameter. The edge weights are all set to 1. + * @param g the input graph + * @param alpha the probability of a hub giving some authority to all vertices, + * and of an authority increasing the score of all hubs (not just those connected + * via links) + */ + public HITS(Graph g, double alpha) + { + super(g, ScoringUtils.getHITSUniformRootPrior(g.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph. The edge weights are all set to 1 + * and alpha is set to 0. + * @param g the input graph + */ + public HITS(Graph g) + { + this(g, 0.0); + } + + + /** + * Maintains hub and authority score information for a vertex. + */ + public static class Scores + { + /** + * The hub score for a vertex. + */ + public double hub; + + /** + * The authority score for a vertex. + */ + public double authority; + + /** + * Creates an instance with the specified hub and authority score. + * @param hub the hub score + * @param authority the authority score + */ + public Scores(double hub, double authority) + { + this.hub = hub; + this.authority = authority; + } + + @Override + public String toString() + { + return String.format("[h:%.4f,a:%.4f]", this.hub, this.authority); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/HITSWithPriors.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,199 @@ +/* + * Created on Jul 14, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A generalization of HITS that permits non-uniformly-distributed random jumps. + * The 'vertex_priors' (that is, prior probabilities for each vertex) may be + * thought of as the fraction of the total 'potential' (hub or authority score) + * that is assigned to that vertex out of the portion that is assigned according + * to random jumps. + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + */ +public class HITSWithPriors + extends AbstractIterativeScorerWithPriors +{ + /** + * The sum of the potential, at each step, associated with vertices with no outedges (authority) + * or no inedges (hub). + */ + protected HITS.Scores disappearing_potential; + + /** + * Creates an instance for the specified graph, edge weights, vertex prior probabilities, + * and random jump probability (alpha). + * @param g the input graph + * @param edge_weights the edge weights + * @param vertex_priors the prior probability for each vertex + * @param alpha the probability of a random jump at each step + */ + public HITSWithPriors(Hypergraph g, + Function edge_weights, + Function vertex_priors, double alpha) + { + super(g, edge_weights, vertex_priors, alpha); + disappearing_potential = new HITS.Scores(0,0); + } + + /** + * Creates an instance for the specified graph, vertex priors, and random + * jump probability (alpha). The edge weights default to 1.0. + * @param g the input graph + * @param vertex_priors the prior probability for each vertex + * @param alpha the probability of a random jump at each step + */ + public HITSWithPriors(Hypergraph g, + Function vertex_priors, double alpha) + { + super(g, Functions.constant(1.0), vertex_priors, alpha); + disappearing_potential = new HITS.Scores(0,0); + } + + /** + * Updates the value for this vertex. + */ + @Override + protected double update(V v) + { + collectDisappearingPotential(v); + + double v_auth = 0; + for (E e : graph.getInEdges(v)) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_auth += (getCurrentValue(w).hub * + getEdgeWeight(w,e).doubleValue() / incident_count); + } +// V w = graph.getOpposite(v, e); +// auth += (getCurrentValue(w).hub * getEdgeWeight(w, e).doubleValue()); + } + + double v_hub = 0; + for (E e : graph.getOutEdges(v)) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_hub += (getCurrentValue(w).authority * + getEdgeWeight(w,e).doubleValue() / incident_count); + } +// V x = graph.getOpposite(v,e); +// hub += (getCurrentValue(x).authority * getEdgeWeight(x, e).doubleValue()); + } + + // modify total_input according to alpha + if (alpha > 0) + { + v_auth = v_auth * (1 - alpha) + getVertexPrior(v).authority * alpha; + v_hub = v_hub * (1 - alpha) + getVertexPrior(v).hub * alpha; + } + setOutputValue(v, new HITS.Scores(v_hub, v_auth)); + + return Math.max(Math.abs(getCurrentValue(v).hub - v_hub), + Math.abs(getCurrentValue(v).authority - v_auth)); + } + + /** + * Code which is executed after each step. In this case, deals with the + * 'disappearing potential', normalizes the scores, and then calls + * super.afterStep(). + * @see #collectDisappearingPotential(Object) + */ + @Override + protected void afterStep() + { + if (disappearing_potential.hub > 0 || disappearing_potential.authority > 0) + { + for (V v : graph.getVertices()) + { + double new_hub = getOutputValue(v).hub + + (1 - alpha) * (disappearing_potential.hub * getVertexPrior(v).hub); + double new_auth = getOutputValue(v).authority + + (1 - alpha) * (disappearing_potential.authority * getVertexPrior(v).authority); + setOutputValue(v, new HITS.Scores(new_hub, new_auth)); + } + disappearing_potential.hub = 0; + disappearing_potential.authority = 0; + } + + normalizeScores(); + + super.afterStep(); + } + + /** + * Normalizes scores so that sum of their squares = 1. + * This method may be overridden so as to yield different + * normalizations. + */ + protected void normalizeScores() { + double hub_ssum = 0; + double auth_ssum = 0; + for (V v : graph.getVertices()) + { + double hub_val = getOutputValue(v).hub; + double auth_val = getOutputValue(v).authority; + hub_ssum += (hub_val * hub_val); + auth_ssum += (auth_val * auth_val); + } + + hub_ssum = Math.sqrt(hub_ssum); + auth_ssum = Math.sqrt(auth_ssum); + + for (V v : graph.getVertices()) + { + HITS.Scores values = getOutputValue(v); + setOutputValue(v, new HITS.Scores( + values.hub / hub_ssum, + values.authority / auth_ssum)); + } + } + + /** + * Collects the "disappearing potential" associated with vertices that have either + * no incoming edges, no outgoing edges, or both. Vertices that have no incoming edges + * do not directly contribute to the hub scores of other vertices; similarly, vertices + * that have no outgoing edges do not directly contribute to the authority scores of + * other vertices. These values are collected at each step and then distributed across all vertices + * as a part of the normalization process. (This process is not required for, and does + * not affect, the 'sum-of-squares'-style normalization.) + */ + @Override + protected void collectDisappearingPotential(V v) + { + if (graph.outDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential.hub += getCurrentValue(v).authority; + else + throw new IllegalArgumentException("Outdegree of " + v + " must be > 0"); + } + if (graph.inDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential.authority += getCurrentValue(v).hub; + else + throw new IllegalArgumentException("Indegree of " + v + " must be > 0"); + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/KStepMarkov.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Aug 22, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A special case of {@code PageRankWithPriors} in which the final scores + * represent a probability distribution over position assuming a random (Markovian) + * walk of exactly k steps, based on the initial distribution specified by the priors. + * + *

    NOTE: The version of {@code KStepMarkov} in {@code algorithms.importance} + * (and in JUNG 1.x) is believed to be incorrect: rather than returning + * a score which represents a probability distribution over position assuming + * a k-step random walk, it returns a score which represents the sum over all steps + * of the probability for each step. If you want that behavior, set the + * 'cumulative' flag as follows before calling {@code evaluate()}: + *

    + *     KStepMarkov ksm = new KStepMarkov(...);
    + *     ksm.setCumulative(true);
    + *     ksm.evaluate();
    + * 
    + * + * By default, the 'cumulative' flag is set to false. + * + * NOTE: THIS CLASS IS NOT YET COMPLETE. USE AT YOUR OWN RISK. (The original behavior + * is captured by the version still available in {@code algorithms.importance}.) + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + * @see PageRank + * @see PageRankWithPriors + */ +public class KStepMarkov extends PageRankWithPriors +{ + private boolean cumulative; + + /** + * Creates an instance based on the specified graph, edge weights, vertex + * priors (initial scores), and number of steps to take. + * @param graph the input graph + * @param edge_weights the edge weights (transition probabilities) + * @param vertex_priors the initial probability distribution (score assignment) + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, Function edge_weights, + Function vertex_priors, int steps) + { + super(graph, edge_weights, vertex_priors, 0); + initialize(steps); + } + + /** + * Creates an instance based on the specified graph, vertex + * priors (initial scores), and number of steps to take. The edge + * weights (transition probabilities) are set to default values (a uniform + * distribution over all outgoing edges). + * @param graph the input graph + * @param vertex_priors the initial probability distribution (score assignment) + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, Function vertex_priors, int steps) + { + super(graph, vertex_priors, 0); + initialize(steps); + } + + /** + * Creates an instance based on the specified graph and number of steps to + * take. The edge weights (transition probabilities) and vertex initial scores + * (prior probabilities) are set to default values (a uniform + * distribution over all outgoing edges, and a uniform distribution over + * all vertices, respectively). + * @param graph the input graph + * @param steps the number of times that {@code step()} will be called by {@code evaluate} + */ + public KStepMarkov(Hypergraph graph, int steps) + { + super(graph, ScoringUtils.getUniformRootPrior(graph.getVertices()), 0); + initialize(steps); + } + + private void initialize(int steps) + { + this.acceptDisconnectedGraph(false); + + if (steps <= 0) + throw new IllegalArgumentException("Number of steps must be > 0"); + + this.max_iterations = steps; + this.tolerance = -1.0; + + this.cumulative = false; + } + + /** + * Specifies whether this instance should assign a score to each vertex + * based on the sum over all steps of the probability for each step. + * See the class-level documentation for details. + * @param cumulative true if this instance should assign a cumulative score to each vertex + */ + public void setCumulative(boolean cumulative) + { + this.cumulative = cumulative; + } + + /** + * Updates the value for this vertex. Called by step(). + */ + @Override + public double update(V v) + { + if (!cumulative) + return super.update(v); + + collectDisappearingPotential(v); + + double v_input = 0; + for (E e : graph.getInEdges(v)) + { + // For graphs, the code below is equivalent to +// V w = graph.getOpposite(v, e); +// total_input += (getCurrentValue(w) * getEdgeWeight(w,e).doubleValue()); + // For hypergraphs, this divides the potential coming from w + // by the number of vertices in the connecting edge e. + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_input += (getCurrentValue(w) * + getEdgeWeight(w,e).doubleValue() / incident_count); + } + } + + // modify total_input according to alpha + double new_value = alpha > 0 ? + v_input * (1 - alpha) + getVertexPrior(v) * alpha : + v_input; + setOutputValue(v, new_value + getCurrentValue(v)); + + // FIXME: DO WE NEED TO CHANGE HOW DISAPPEARING IS COUNTED? NORMALIZE? + + return Math.abs(getCurrentValue(v) - new_value); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ + + + + + + + +Mechanisms for assigning values (denoting significance, influence, centrality, etc.) +to graph elements based on topological properties. These include: + +
      +
    • BarycenterScorer: assigns a score to each vertex according to +the sum of the distances to all other vertices +
    • ClosenessCentrality: assigns a score to each vertex based on +the mean distance to each other vertex +
    • DegreeScorer: assigns a score to each vertex based on its degree +
    • EigenvectorCentrality: assigns vertex scores based on +long-term probabilities of random walks passing through the vertex at time t +
    • PageRank: like EigenvectorCentrality, but with +a constant probability of the +random walk restarting at a uniform-randomly chosen vertex +
    • PageRankWithPriors: like PageRank, but with a +constant probability of the random +walk restarting at a vertex drawn from an arbitrary distribution +
    • HITS: assigns hubs-and-authorities scores to vertices based on +complementary random walk processes +
    • HITSWithPriors: analogous to HITS +(see PageRankWithPriors) +
    • VoltageScorer: assigns scores to vertices based on simulated +current flow along edges +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRank.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to each vertex according to the PageRank algorithm. + * + *

    PageRank is an eigenvector-based algorithm. The score for a given vertex may be thought of + * as the fraction of time spent 'visiting' that vertex (measured over all time) + * in a random walk over the vertices (following outgoing edges from each vertex). + * PageRank modifies this random walk by adding to the model a probability (specified as 'alpha' + * in the constructor) of jumping to any vertex. If alpha is 0, this is equivalent to the + * eigenvector centrality algorithm; if alpha is 1, all vertices will receive the same score + * (1/|V|). Thus, alpha acts as a sort of score smoothing parameter. + * + *

    The original algorithm assumed that, for a given vertex, the probability of following any + * outgoing edge was the same; this is the default if edge weights are not specified. + * This implementation generalizes the original by permitting + * the user to specify edge weights; in order to maintain the original semantics, however, + * the weights on the outgoing edges for a given vertex must represent transition probabilities; + * that is, they must sum to 1. + * + *

    If a vertex has no outgoing edges, then the probability of taking a random jump from that + * vertex is (by default) effectively 1. If the user wishes to instead throw an exception when this happens, + * call acceptDisconnectedGraph(false) on this instance. + * + *

    Typical values for alpha (according to the original paper) are in the range [0.1, 0.2] + * but may be any value between 0 and 1 inclusive. + * + * @see "The Anatomy of a Large-Scale Hypertextual Web Search Engine by L. Page and S. Brin, 1999" + */ +public class PageRank extends PageRankWithPriors +{ + + /** + * Creates an instance for the specified graph, edge weights, and random jump probability. + * @param graph the input graph + * @param edge_weight the edge weights (transition probabilities) + * @param alpha the probability of taking a random jump to an arbitrary vertex + */ + public PageRank(Hypergraph graph, Function edge_weight, double alpha) + { + super(graph, edge_weight, ScoringUtils.getUniformRootPrior(graph.getVertices()), alpha); + } + + /** + * Creates an instance for the specified graph and random jump probability; the probability + * of following any outgoing edge from a given vertex is the same. + * @param graph the input graph + * @param alpha the probability of taking a random jump to an arbitrary vertex + */ + public PageRank(Hypergraph graph, double alpha) + { + super(graph, ScoringUtils.getUniformRootPrior(graph.getVertices()), alpha); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/PageRankWithPriors.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * A generalization of PageRank that permits non-uniformly-distributed random jumps. + * The 'vertex_priors' (that is, prior probabilities for each vertex) may be + * thought of as the fraction of the total 'potential' that is assigned to that + * vertex at each step out of the portion that is assigned according + * to random jumps (this portion is specified by 'alpha'). + * + * @see "Algorithms for Estimating Relative Importance in Graphs by Scott White and Padhraic Smyth, 2003" + * @see PageRank + */ +public class PageRankWithPriors + extends AbstractIterativeScorerWithPriors +{ + /** + * Maintains the amount of potential associated with vertices with no out-edges. + */ + protected double disappearing_potential = 0.0; + + /** + * Creates an instance with the specified graph, edge weights, vertex priors, and + * 'random jump' probability (alpha). + * @param graph the input graph + * @param edge_weights the edge weights, denoting transition probabilities from source to destination + * @param vertex_priors the prior probabilities for each vertex + * @param alpha the probability of executing a 'random jump' at each step + */ + public PageRankWithPriors(Hypergraph graph, + Function edge_weights, + Function vertex_priors, double alpha) + { + super(graph, edge_weights, vertex_priors, alpha); + } + + /** + * Creates an instance with the specified graph, vertex priors, and + * 'random jump' probability (alpha). The outgoing edge weights for each + * vertex will be equal and sum to 1. + * @param graph the input graph + * @param vertex_priors the prior probabilities for each vertex + * @param alpha the probability of executing a 'random jump' at each step + */ + public PageRankWithPriors(Hypergraph graph, + Function vertex_priors, double alpha) + { + super(graph, vertex_priors, alpha); + this.edge_weights = new UniformDegreeWeight(graph); + } + + /** + * Updates the value for this vertex. Called by step(). + */ + @Override + public double update(V v) + { + collectDisappearingPotential(v); + + double v_input = 0; + for (E e : graph.getInEdges(v)) + { + // For graphs, the code below is equivalent to +// V w = graph.getOpposite(v, e); +// total_input += (getCurrentValue(w) * getEdgeWeight(w,e).doubleValue()); + // For hypergraphs, this divides the potential coming from w + // by the number of vertices in the connecting edge e. + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + v_input += (getCurrentValue(w) * + getEdgeWeight(w,e).doubleValue() / incident_count); + } + } + + // modify total_input according to alpha + double new_value = alpha > 0 ? + v_input * (1 - alpha) + getVertexPrior(v) * alpha : + v_input; + setOutputValue(v, new_value); + + return Math.abs(getCurrentValue(v) - new_value); + } + + /** + * Cleans up after each step. In this case that involves allocating the disappearing + * potential (thus maintaining normalization of the scores) according to the vertex + * probability priors, and then calling + * super.afterStep. + */ + @Override + protected void afterStep() + { + // distribute disappearing potential according to priors + if (disappearing_potential > 0) + { + for (V v : graph.getVertices()) + { + setOutputValue(v, getOutputValue(v) + + (1 - alpha) * (disappearing_potential * getVertexPrior(v))); + } + disappearing_potential = 0; + } + + super.afterStep(); + } + + /** + * Collects the "disappearing potential" associated with vertices that have + * no outgoing edges. Vertices that have no outgoing edges do not directly + * contribute to the scores of other vertices. These values are collected + * at each step and then distributed across all vertices + * as a part of the normalization process. + */ + @Override + protected void collectDisappearingPotential(V v) + { + if (graph.outDegree(v) == 0) + { + if (isDisconnectedGraphOK()) + disappearing_potential += getCurrentValue(v); + else + throw new IllegalArgumentException("Outdegree of " + v + " must be > 0"); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/DelegateToEdgeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Created on Jul 11, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import com.google.common.base.Function; + +/** + * A {@code Transformer}. Mainly useful for technical reasons inside + * AbstractIterativeScorer; in essence it allows the edge weight instance + * variable to be of type VEPair,W even if the edge weight + * Transformer only operates on edges. + */ +public class DelegateToEdgeTransformer implements + Function,Number> +{ + /** + * The Function to which this instance delegates its function. + */ + protected Function delegate; + + /** + * Creates an instance with the specified delegate Function. + * @param delegate the Function to which this instance will delegate + */ + public DelegateToEdgeTransformer(Function delegate) + { + this.delegate = delegate; + } + + /** + * @see Function#apply(Object) + */ + public Number apply(VEPair arg0) + { + return delegate.apply(arg0.getE()); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,34 @@ + + + + + + + +Utility functions for assigning scores to graph elements. These include: +

      +
    • EdgeWeight: interface for classes that associate numeric values +with edges +
    • ScoringUtils: methods for calculating transition probabilities +for random-walk-based algorithms. +
    • UniformOut: an edge weight function that assigns weights as uniform +transition probabilities to all outgoing edges of a vertex. +
    • UniformIncident: an edge weight function that assigns +weights as uniform transition probabilities to all incident edges of a +vertex (useful for undirected graphs). +
    • VEPair: analogous to Pair but specifically +containing an associated vertex and edge. +
    • VertexEdgeWeight: a subtype of EdgeWeight that +assigns edge weights with respect to a specified 'source' vertex. +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/ScoringUtils.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Created on Jul 12, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import java.util.Collection; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.HITS; + +/** + * Methods for assigning values (to be interpreted as prior probabilities) to vertices in the context + * of random-walk-based scoring algorithms. + */ +public class ScoringUtils +{ + /** + * Assigns a probability of 1/roots.size() to each of the elements of roots. + * @param the vertex type + * @param roots the vertices to be assigned nonzero prior probabilities + * @return a Function assigning a uniform prior to each element in {@code roots} + */ + public static Function getUniformRootPrior(Collection roots) + { + final Collection inner_roots = roots; + Function distribution = new Function() + { + public Double apply(V input) + { + if (inner_roots.contains(input)) + return new Double(1.0 / inner_roots.size()); + else + return 0.0; + } + }; + + return distribution; + } + + /** + * Returns a Function that hub and authority values of 1/roots.size() to each + * element of roots. + * @param the vertex type + * @param roots the vertices to be assigned nonzero scores + * @return a Function that assigns uniform prior hub/authority probabilities to each root + */ + public static Function getHITSUniformRootPrior(Collection roots) + { + final Collection inner_roots = roots; + Function distribution = + new Function() + { + public HITS.Scores apply(V input) + { + if (inner_roots.contains(input)) + return new HITS.Scores(1.0 / inner_roots.size(), 1.0 / inner_roots.size()); + else + return new HITS.Scores(0.0, 0.0); + } + }; + return distribution; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformDegreeWeight.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jul 14, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * An edge weight function that assigns weights as uniform + * transition probabilities. + * For undirected edges, returns 1/degree(v) (where 'v' is the + * vertex in the VEPair. + * For directed edges, returns 1/outdegree(source(e)) (where 'e' + * is the edge in the VEPair). + * Throws an IllegalArgumentException if the input + * edge is neither EdgeType.UNDIRECTED nor EdgeType.DIRECTED. + * + */ +public class UniformDegreeWeight implements + Function, Double> +{ + private Hypergraph graph; + + /** + * @param graph the graph for which an instance is being created + */ + public UniformDegreeWeight(Hypergraph graph) + { + this.graph = graph; + } + + public Double apply(VEPair ve_pair) + { + E e = ve_pair.getE(); + V v = ve_pair.getV(); + EdgeType edge_type = graph.getEdgeType(e); + if (edge_type == EdgeType.UNDIRECTED) + return 1.0 / graph.degree(v); + if (edge_type == EdgeType.DIRECTED) + return 1.0 / graph.outDegree(graph.getSource(e)); + throw new IllegalArgumentException("can't handle edge type: " + edge_type); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/UniformInOut.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * Created on Jul 11, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * Assigns weights to directed edges (the edge of the vertex/edge pair) depending on + * whether the vertex is the edge's source or its destination. + * If the vertex v is the edge's source, assigns 1/outdegree(v). + * Otherwise, assigns 1/indegree(w). + * Throws IllegalArgumentException if the edge is not directed. + */ +public class UniformInOut implements Function, Double> +{ + /** + * The graph for which the edge weights are defined. + */ + protected Graph graph; + + /** + * Creates an instance for the specified graph. + * @param graph the graph for which the edge weights will be defined + */ + public UniformInOut(Graph graph) + { + this.graph = graph; + } + + public Double apply(VEPair ve_pair) + { + V v = ve_pair.getV(); + E e = ve_pair.getE(); + if (graph.getEdgeType(e) != EdgeType.DIRECTED) + throw new IllegalArgumentException("This Function only" + + " operates on directed edges"); + return 1.0 / (graph.isSource(v, e) ? + graph.outDegree(v) : + graph.inDegree(v)); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VEPair.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * Created on Jul 8, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +/** + * Convenience class for associating a vertex and an edge. Used, for example, + * in contexts in which it is necessary to know the origin for an edge traversal + * (that is, the direction in which an (undirected) edge is being traversed). + * + * @param the vertex type + * @param the edge type + */ +public class VEPair +{ + private V v; + private E e; + + /** + * Creates an instance with the specified vertex and edge + * @param v the vertex to add + * @param e the edge to add + */ + public VEPair(V v, E e) + { + if (v == null || e == null) + throw new IllegalArgumentException("elements must be non-null"); + + this.v = v; + this.e = e; + } + + /** + * @return the vertex of this pair + */ + public V getV() + { + return v; + } + + /** + * @return the edge of this pair + */ + public E getE() + { + return e; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/util/VertexScoreTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Created on Jul 18, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring.util; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.VertexScorer; + +/** + * A Function convenience wrapper around VertexScorer. + */ +public class VertexScoreTransformer implements Function +{ + /** + * The VertexScorer instance that provides the values returned by transform. + */ + protected VertexScorer vs; + + /** + * Creates an instance based on the specified VertexScorer. + * @param vs the VertexScorer which will retrieve the score for each vertex + */ + public VertexScoreTransformer(VertexScorer vs) + { + this.vs = vs; + } + + /** + * @param v the vertex whose score is being returned + * @return the score for this vertex. + */ + public S apply(V v) + { + return vs.getVertexScore(v); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VertexScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Created on Jul 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + + +/** + * An interface for algorithms that assign scores to vertices. + * + * @param the vertex type + * @param the score type + */ +public interface VertexScorer +{ + /** + * @param v the vertex whose score is requested + * @return the algorithm's score for this vertex + */ + public S getVertexScore(V v); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/scoring/VoltageScorer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,250 @@ +/* + * Created on Jul 15, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.util.UniformDegreeWeight; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Assigns scores to vertices according to their 'voltage' in an approximate + * solution to the Kirchoff equations. This is accomplished by tying "source" + * vertices to specified positive voltages, "sink" vertices to 0 V, and + * iteratively updating the voltage of each other vertex to the (weighted) + * average of the voltages of its neighbors. + * + *

    The resultant voltages will all be in the range [0, max] + * where max is the largest voltage of any source vertex (in the + * absence of negative source voltages; see below). + * + *

    A few notes about this algorithm's interpretation of the graph data: + *

      + *
    • Higher edge weights are interpreted as indicative of greater + * influence/effect than lower edge weights. + *
    • Negative edge weights (and negative "source" voltages) invalidate + * the interpretation of the resultant values as voltages. However, this + * algorithm will not reject graphs with negative edge weights or source voltages. + *
    • Parallel edges are equivalent to a single edge whose weight is the + * sum of the weights on the parallel edges. + *
    • Current flows along undirected edges in both directions, + * but only flows along directed edges in the direction of the edge. + *
    + * + */ +public class VoltageScorer extends AbstractIterativeScorer + implements VertexScorer +{ + protected Map source_voltages; + protected Collection sinks; + + /** + * Creates an instance with the specified graph, edge weights, source voltages, + * and sinks. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param source_voltages the (fixed) voltage for each source + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Function edge_weights, + Map source_voltages, Collection sinks) + { + super(g, edge_weights); + this.source_voltages = source_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source vertices + * (each of whose 'voltages' are tied to 1), and sinks. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param sources the vertices whose voltages are tied to 1 + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Function edge_weights, + Collection sources, Collection sinks) + { + super(g, edge_weights); + + Map unit_voltages = new HashMap(); + for(V v : sources) + unit_voltages.put(v, new Double(1.0)); + this.source_voltages = unit_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, source vertices + * (each of whose 'voltages' are tied to 1), and sinks. + * The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param sources the vertices whose voltages are tied to 1 + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Collection sources, Collection sinks) + { + super(g); + + Map unit_voltages = new HashMap(); + for(V v : sources) + unit_voltages.put(v, new Double(1.0)); + this.source_voltages = unit_voltages; + this.sinks = sinks; + initialize(); + } + + /** + * Creates an instance with the specified graph, source voltages, + * and sinks. The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param source_voltages the (fixed) voltage for each source + * @param sinks the vertices whose voltages are tied to 0 + */ + public VoltageScorer(Hypergraph g, Map source_voltages, + Collection sinks) + { + super(g); + this.source_voltages = source_voltages; + this.sinks = sinks; + this.edge_weights = new UniformDegreeWeight(g); + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source, and + * sink. The source vertex voltage is tied to 1. + * @param g the input graph + * @param edge_weights the edge weights, representing conductivity + * @param source the vertex whose voltage is tied to 1 + * @param sink the vertex whose voltage is tied to 0 + */ + public VoltageScorer(Hypergraph g, Function edge_weights, + V source, V sink) + { + this(g, edge_weights, Collections.singletonMap(source, 1.0), Collections.singletonList(sink)); + initialize(); + } + + /** + * Creates an instance with the specified graph, edge weights, source, and + * sink. The source vertex voltage is tied to 1. + * The outgoing edges for each vertex are assigned + * weights that sum to 1. + * @param g the input graph + * @param source the vertex whose voltage is tied to 1 + * @param sink the vertex whose voltage is tied to 0 + */ + public VoltageScorer(Hypergraph g, V source, V sink) + { + this(g, Collections.singletonMap(source, 1.0), Collections.singletonList(sink)); + initialize(); + } + + + /** + * Initializes the state of this instance. + */ + @Override + public void initialize() + { + super.initialize(); + + // sanity check + if (source_voltages.isEmpty() || sinks.isEmpty()) + throw new IllegalArgumentException("Both sources and sinks (grounds) must be defined"); + + if (source_voltages.size() + sinks.size() > graph.getVertexCount()) + throw new IllegalArgumentException("Source/sink sets overlap, or contain vertices not in graph"); + + for (Map.Entry entry : source_voltages.entrySet()) + { + V v = entry.getKey(); + if (sinks.contains(v)) + throw new IllegalArgumentException("Vertex " + v + " is incorrectly specified as both source and sink"); + double value = entry.getValue().doubleValue(); + if (value <= 0) + throw new IllegalArgumentException("Source vertex " + v + " has negative voltage"); + } + + // set up initial voltages + for (V v : graph.getVertices()) + { + if (source_voltages.containsKey(v)) + setOutputValue(v, source_voltages.get(v).doubleValue()); + else + setOutputValue(v, 0.0); + } + } + + /** + * @see edu.uci.ics.jung.algorithms.scoring.AbstractIterativeScorer#update(Object) + */ + @Override + public double update(V v) + { + // if it's a voltage source or sink, we're done + Number source_volts = source_voltages.get(v); + if (source_volts != null) + { + setOutputValue(v, source_volts.doubleValue()); + return 0.0; + } + if (sinks.contains(v)) + { + setOutputValue(v, 0.0); + return 0.0; + } + + Collection edges = graph.getInEdges(v); + double voltage_sum = 0; + double weight_sum = 0; + for (E e: edges) + { + int incident_count = getAdjustedIncidentCount(e); + for (V w : graph.getIncidentVertices(e)) + { + if (!w.equals(v) || hyperedges_are_self_loops) + { + double weight = getEdgeWeight(w,e).doubleValue() / incident_count; + voltage_sum += getCurrentValue(w).doubleValue() * weight; + weight_sum += weight; + } + } +// V w = graph.getOpposite(v, e); +// double weight = getEdgeWeight(w,e).doubleValue(); +// voltage_sum += getCurrentValue(w).doubleValue() * weight; +// weight_sum += weight; + } + + // if either is 0, new value is 0 + if (voltage_sum == 0 || weight_sum == 0) + { + setOutputValue(v, 0.0); + return getCurrentValue(v).doubleValue(); + } + + setOutputValue(v, voltage_sum / weight_sum); + return Math.abs(getCurrentValue(v).doubleValue() - voltage_sum / weight_sum); + } + +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/BFSDistanceLabeler.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Labels each node in the graph according to the BFS distance from the start node(s). If nodes are unreachable, then + * they are assigned a distance of -1. + * All nodes traversed at step k are marked as predecessors of their successors traversed at step k+1. + *

    + * Running time is: O(m) + * @author Scott White + */ +public class BFSDistanceLabeler { + + private Map distanceDecorator = new HashMap(); + private List mCurrentList; + private Set mUnvisitedVertices; + private List mVerticesInOrderVisited; + private Map> mPredecessorMap; + + /** + * Creates a new BFS labeler for the specified graph and root set + * The distances are stored in the corresponding Vertex objects and are of type MutableInteger + */ + public BFSDistanceLabeler() { + mPredecessorMap = new HashMap>(); + } + + /** + * Returns the list of vertices visited in order of traversal + * @return the list of vertices + */ + public List getVerticesInOrderVisited() { + return mVerticesInOrderVisited; + } + + /** + * Returns the set of all vertices that were not visited + * @return the list of unvisited vertices + */ + public Set getUnvisitedVertices() { + return mUnvisitedVertices; + } + + /** + * Given a vertex, returns the shortest distance from any node in the root set to v + * @param g the graph in which the distances are to be measured + * @param v the vertex whose distance is to be retrieved + * @return the shortest distance from any node in the root set to v + */ + public int getDistance(Hypergraph g, V v) { + if (!g.getVertices().contains(v)) { + throw new IllegalArgumentException("Vertex is not contained in the graph."); + } + + return distanceDecorator.get(v).intValue(); + } + + /** + * Returns set of predecessors of the given vertex + * @param v the vertex whose predecessors are to be retrieved + * @return the set of predecessors + */ + public Set getPredecessors(V v) { + return mPredecessorMap.get(v); + } + + protected void initialize(Hypergraph g, Set rootSet) { + mVerticesInOrderVisited = new ArrayList(); + mUnvisitedVertices = new HashSet(); + for(V currentVertex : g.getVertices()) { + mUnvisitedVertices.add(currentVertex); + mPredecessorMap.put(currentVertex,new HashSet()); + } + + mCurrentList = new ArrayList(); + for(V v : rootSet) { + distanceDecorator.put(v, new Integer(0)); + mCurrentList.add(v); + mUnvisitedVertices.remove(v); + mVerticesInOrderVisited.add(v); + } + } + + private void addPredecessor(V predecessor,V sucessor) { + HashSet predecessors = mPredecessorMap.get(sucessor); + predecessors.add(predecessor); + } + + /** + * Computes the distances of all the node from the starting root nodes. If there is more than one root node + * the minimum distance from each root node is used as the designated distance to a given node. Also keeps track + * of the predecessors of each node traversed as well as the order of nodes traversed. + * @param graph the graph to label + * @param rootSet the set of starting vertices to traverse from + */ + public void labelDistances(Hypergraph graph, Set rootSet) { + + initialize(graph,rootSet); + + int distance = 1; + while (true) { + List newList = new ArrayList(); + for(V currentVertex : mCurrentList) { + if(graph.containsVertex(currentVertex)) { + for(V next : graph.getSuccessors(currentVertex)) { + visitNewVertex(currentVertex,next, distance, newList); + } + } + } + if (newList.size() == 0) break; + mCurrentList = newList; + distance++; + } + + for(V v : mUnvisitedVertices) { + distanceDecorator.put(v,new Integer(-1)); + } + } + + /** + * Computes the distances of all the node from the specified root node. Also keeps track + * of the predecessors of each node traversed as well as the order of nodes traversed. + * @param graph the graph to label + * @param root the single starting vertex to traverse from + */ + public void labelDistances(Hypergraph graph, V root) { + labelDistances(graph, Collections.singleton(root)); + } + + private void visitNewVertex(V predecessor, V neighbor, int distance, List newList) { + if (mUnvisitedVertices.contains(neighbor)) { + distanceDecorator.put(neighbor, new Integer(distance)); + newList.add(neighbor); + mVerticesInOrderVisited.add(neighbor); + mUnvisitedVertices.remove(neighbor); + } + int predecessorDistance = distanceDecorator.get(predecessor).intValue(); + int successorDistance = distanceDecorator.get(neighbor).intValue(); + if (predecessorDistance < successorDistance) { + addPredecessor(predecessor,neighbor); + } + } + + /** + * Must be called after {@code labelDistances} in order to contain valid data. + * @return a map from vertices to minimum distances from the original source(s) + */ + public Map getDistanceDecorator() { + return distanceDecorator; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraDistance.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,545 @@ +/* + * Created on Jul 9, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.util.BasicMapEntry; +import edu.uci.ics.jung.algorithms.util.MapBinaryHeap; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + *

    Calculates distances in a specified graph, using + * Dijkstra's single-source-shortest-path algorithm. All edge weights + * in the graph must be nonnegative; if any edge with negative weight is + * found in the course of calculating distances, an + * IllegalArgumentException will be thrown. + * (Note: this exception will only be thrown when such an edge would be + * used to update a given tentative distance; + * the algorithm does not check for negative-weight edges "up front".) + * + *

    Distances and partial results are optionally cached (by this instance) + * for later reference. Thus, if the 10 closest vertices to a specified source + * vertex are known, calculating the 20 closest vertices does not require + * starting Dijkstra's algorithm over from scratch. + * + *

    Distances are stored as double-precision values. + * If a vertex is not reachable from the specified source vertex, no + * distance is stored. This is new behavior with version 1.4; + * the previous behavior was to store a value of + * Double.POSITIVE_INFINITY. This change gives the algorithm + * an approximate complexity of O(kD log k), where k is either the number of + * requested targets or the number of reachable vertices (whichever is smaller), + * and D is the average degree of a vertex. + * + *

    The elements in the maps returned by getDistanceMap + * are ordered (that is, returned + * by the iterator) by nondecreasing distance from source. + * + *

    Users are cautioned that distances calculated should be assumed to + * be invalidated by changes to the graph, and should invoke reset() + * when appropriate so that the distances can be recalculated. + * + * @author Joshua O'Madadhain + * @author Tom Nelson converted to jung2 + */ +public class DijkstraDistance implements Distance +{ + protected Hypergraph g; + protected Function nev; + protected Map sourceMap; // a map of source vertices to an instance of SourceData + protected boolean cached; + protected double max_distance; + protected int max_targets; + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally if and only if + * cached is true. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + * @param cached specifies whether the results are to be cached + */ + public DijkstraDistance(Hypergraph g, Function nev, boolean cached) { + this.g = g; + this.nev = nev; + this.sourceMap = new HashMap(); + this.cached = cached; + this.max_distance = Double.POSITIVE_INFINITY; + this.max_targets = Integer.MAX_VALUE; + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + */ + public DijkstraDistance(Hypergraph g, Function nev) { + this(g, nev, true); + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + */ + public DijkstraDistance(Graph g) { + this(g, Functions.constant(1), true); + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + * @param cached specifies whether the results are to be cached + */ + public DijkstraDistance(Graph g, boolean cached) { + this(g, Functions.constant(1), cached); + } + + /** + * Implements Dijkstra's single-source shortest-path algorithm for + * weighted graphs. Uses a MapBinaryHeap as the priority queue, + * which gives this algorithm a time complexity of O(m lg n) (m = # of edges, n = + * # of vertices). + * This algorithm will terminate when any of the following have occurred (in order + * of priority): + *

      + *
    • the distance to the specified target (if any) has been found + *
    • no more vertices are reachable + *
    • the specified # of distances have been found, or the maximum distance + * desired has been exceeded + *
    • all distances have been found + *
    + * + * @param source the vertex from which distances are to be measured + * @param numDests the number of distances to measure + * @param targets the set of vertices to which distances are to be measured + * @return a mapping from vertex to the shortest distance from the source to each target + */ + protected LinkedHashMap singleSourceShortestPath(V source, Collection targets, int numDests) + { + SourceData sd = getSourceData(source); + + Set to_get = new HashSet(); + if (targets != null) { + to_get.addAll(targets); + Set existing_dists = sd.distances.keySet(); + for(V o : targets) { + if (existing_dists.contains(o)) + to_get.remove(o); + } + } + + // if we've exceeded the max distance or max # of distances we're willing to calculate, or + // if we already have all the distances we need, + // terminate + if (sd.reached_max || + (targets != null && to_get.isEmpty()) || + (sd.distances.size() >= numDests)) + { + return sd.distances; + } + + while (!sd.unknownVertices.isEmpty() && (sd.distances.size() < numDests || !to_get.isEmpty())) + { + Map.Entry p = sd.getNextVertex(); + V v = p.getKey(); + double v_dist = p.getValue().doubleValue(); + to_get.remove(v); + if (v_dist > this.max_distance) + { + // we're done; put this vertex back in so that we're not including + // a distance beyond what we specified + sd.restoreVertex(v, v_dist); + sd.reached_max = true; + break; + } + sd.dist_reached = v_dist; + + if (sd.distances.size() >= this.max_targets) + { + sd.reached_max = true; + break; + } + + for (E e : getEdgesToCheck(v) ) + { + for (V w : g.getIncidentVertices(e)) + { + if (!sd.distances.containsKey(w)) + { + double edge_weight = nev.apply(e).doubleValue(); + if (edge_weight < 0) + throw new IllegalArgumentException("Edges weights must be non-negative"); + double new_dist = v_dist + edge_weight; + if (!sd.estimatedDistances.containsKey(w)) + { + sd.createRecord(w, e, new_dist); + } + else + { + double w_dist = ((Double)sd.estimatedDistances.get(w)).doubleValue(); + if (new_dist < w_dist) // update tentative distance & path for w + sd.update(w, e, new_dist); + } + } + } + } + } + return sd.distances; + } + + protected SourceData getSourceData(V source) + { + SourceData sd = sourceMap.get(source); + if (sd == null) + sd = new SourceData(source); + return sd; + } + + /** + * Returns the set of edges incident to v that should be tested. + * By default, this is the set of outgoing edges for instances of Graph, + * the set of incident edges for instances of Hypergraph, + * and is otherwise undefined. + * @param v the vertex whose edges are to be checked + * @return the set of edges incident to {@code v} that should be tested + */ + protected Collection getEdgesToCheck(V v) + { + if (g instanceof Graph) + return ((Graph)g).getOutEdges(v); + else + return g.getIncidentEdges(v); + + } + + + /** + * Returns the length of a shortest path from the source to the target vertex, + * or null if the target is not reachable from the source. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + * + * @param source the vertex from which the distance to {@code target} is to be measured + * @param target the vertex to which the distance from {@code source} is to be measured + * @return the distance between {@code source} and {@code target} + * + * @see #getDistanceMap(Object) + * @see #getDistanceMap(Object,int) + */ + public Number getDistance(V source, V target) + { + if (g.containsVertex(target) == false) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + if (g.containsVertex(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + Set targets = new HashSet(); + targets.add(target); + Map distanceMap = getDistanceMap(source, targets); + return distanceMap.get(target); + } + + + /** + * Returns a {@code Map} from each element {@code t} of {@code targets} to the + * shortest-path distance from {@code source} to {@code t}. + * @param source the vertex from which the distance to each target is to be measured + * @param targets the vertices to which the distance from the source is to be measured + * @return {@code Map} from each element of {@code targets} to its distance from {@code source} + */ + public Map getDistanceMap(V source, Collection targets) + { + if (g.containsVertex(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + if (targets.size() > max_targets) + throw new IllegalArgumentException("size of target set exceeds maximum " + + "number of targets allowed: " + this.max_targets); + + Map distanceMap = + singleSourceShortestPath(source, targets, + Math.min(g.getVertexCount(), max_targets)); + if (!cached) + reset(source); + + return distanceMap; + } + + /** + *

    Returns a LinkedHashMap which maps each vertex + * in the graph (including the source vertex) + * to its distance from the source vertex. + * The map's iterator will return the elements in order of + * increasing distance from source. + * + *

    The size of the map returned will be the number of + * vertices reachable from source. + * + * @see #getDistanceMap(Object,int) + * @see #getDistance(Object,Object) + * @param source the vertex from which distances are measured + * @return a mapping from each vertex in the graph to its distance from {@code source} + */ + public Map getDistanceMap(V source) + { + return getDistanceMap(source, Math.min(g.getVertexCount(), max_targets)); + } + + + + /** + *

    Returns a LinkedHashMap which maps each of the closest + * numDist vertices to the source vertex + * in the graph (including the source vertex) + * to its distance from the source vertex. Throws + * an IllegalArgumentException if source + * is not in this instance's graph, or if numDests is + * either less than 1 or greater than the number of vertices in the + * graph. + * + *

    The size of the map returned will be the smaller of + * numDests and the number of vertices reachable from + * source. + * + * @see #getDistanceMap(Object) + * @see #getDistance(Object,Object) + * @param source the vertex from which distances are measured + * @param numDests the number of vertices for which to measure distances + * @return a mapping from the {@code numDests} vertices in the graph + * closest to {@code source}, to their distance from {@code source} + * + */ + public LinkedHashMap getDistanceMap(V source, int numDests) + { + + if(g.getVertices().contains(source) == false) { + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + } + if (numDests < 1 || numDests > g.getVertexCount()) + throw new IllegalArgumentException("numDests must be >= 1 " + + "and <= g.numVertices()"); + + if (numDests > max_targets) + throw new IllegalArgumentException("numDests must be <= the maximum " + + "number of targets allowed: " + this.max_targets); + + LinkedHashMap distanceMap = + singleSourceShortestPath(source, null, numDests); + + if (!cached) + reset(source); + + return distanceMap; + } + + /** + * Allows the user to specify the maximum distance that this instance will calculate. + * Any vertices past this distance will effectively be unreachable from the source, in + * the sense that the algorithm will not calculate the distance to any vertices which + * are farther away than this distance. A negative value for max_dist + * will ensure that no further distances are calculated. + * + *

    This can be useful for limiting the amount of time and space used by this algorithm + * if the graph is very large. + * + *

    Note: if this instance has already calculated distances greater than max_dist, + * and the results are cached, those results will still be valid and available; this limit + * applies only to subsequent distance calculations. + * + * @param max_dist the maximum distance that this instance will calculate + * + * @see #setMaxTargets(int) + */ + public void setMaxDistance(double max_dist) + { + this.max_distance = max_dist; + for (V v : sourceMap.keySet()) + { + SourceData sd = sourceMap.get(v); + sd.reached_max = (this.max_distance <= sd.dist_reached) || (sd.distances.size() >= max_targets); + } + } + + /** + * Allows the user to specify the maximum number of target vertices per source vertex + * for which this instance will calculate distances. Once this threshold is reached, + * any further vertices will effectively be unreachable from the source, in + * the sense that the algorithm will not calculate the distance to any more vertices. + * A negative value for max_targets will ensure that no further distances are calculated. + * + *

    This can be useful for limiting the amount of time and space used by this algorithm + * if the graph is very large. + * + *

    Note: if this instance has already calculated distances to a greater number of + * targets than max_targets, and the results are cached, those results + * will still be valid and available; this limit applies only to subsequent distance + * calculations. + * + * @param max_targets the maximum number of targets for which this instance will calculate + * distances + * + * @see #setMaxDistance(double) + */ + public void setMaxTargets(int max_targets) + { + this.max_targets = max_targets; + for (V v : sourceMap.keySet()) + { + SourceData sd = sourceMap.get(v); + sd.reached_max = (this.max_distance <= sd.dist_reached) || (sd.distances.size() >= max_targets); + } + } + + /** + * Clears all stored distances for this instance. + * Should be called whenever the graph is modified (edge weights + * changed or edges added/removed). If the user knows that + * some currently calculated distances are unaffected by a + * change, reset(V) may be appropriate instead. + * + * @see #reset(Object) + */ + public void reset() + { + sourceMap = new HashMap(); + } + + /** + * Specifies whether or not this instance of DijkstraShortestPath + * should cache its results (final and partial) for future reference. + * + * @param enable true if the results are to be cached, and + * false otherwise + */ + public void enableCaching(boolean enable) + { + this.cached = enable; + } + + /** + * Clears all stored distances for the specified source vertex + * source. Should be called whenever the stored distances + * from this vertex are invalidated by changes to the graph. + * + * @param source the vertex for which stored distances should be cleared + * + * @see #reset() + */ + public void reset(V source) + { + sourceMap.put(source, null); + } + + /** + * Compares according to distances, so that the BinaryHeap knows how to + * order the tree. + */ + protected static class VertexComparator implements Comparator + { + private Map distances; + + protected VertexComparator(Map distances) + { + this.distances = distances; + } + + public int compare(V o1, V o2) + { + return ((Double) distances.get(o1)).compareTo((Double) distances.get(o2)); + } + } + + /** + * For a given source vertex, holds the estimated and final distances, + * tentative and final assignments of incoming edges on the shortest path from + * the source vertex, and a priority queue (ordered by estimated distance) + * of the vertices for which distances are unknown. + * + * @author Joshua O'Madadhain + */ + protected class SourceData + { + protected LinkedHashMap distances; + protected Map estimatedDistances; + protected MapBinaryHeap unknownVertices; + protected boolean reached_max = false; + protected double dist_reached = 0; + + protected SourceData(V source) + { + distances = new LinkedHashMap(); + estimatedDistances = new HashMap(); + unknownVertices = new MapBinaryHeap(new VertexComparator(estimatedDistances)); + + sourceMap.put(source, this); + + // initialize priority queue + estimatedDistances.put(source, new Double(0)); // distance from source to itself is 0 + unknownVertices.add(source); + reached_max = false; + dist_reached = 0; + } + + protected Map.Entry getNextVertex() + { + V v = unknownVertices.remove(); + Double dist = (Double)estimatedDistances.remove(v); + distances.put(v, dist); + return new BasicMapEntry(v, dist); + } + + protected void update(V dest, E tentative_edge, double new_dist) + { + estimatedDistances.put(dest, new_dist); + unknownVertices.update(dest); + } + + protected void createRecord(V w, E e, double new_dist) + { + estimatedDistances.put(w, new_dist); + unknownVertices.add(w); + } + + protected void restoreVertex(V v, double dist) + { + estimatedDistances.put(v, dist); + unknownVertices.add(v); + distances.remove(v); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DijkstraShortestPath.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,297 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; + +/** + *

    Calculates distances and shortest paths using Dijkstra's + * single-source-shortest-path algorithm. This is a lightweight + * extension of DijkstraDistance that also stores + * path information, so that the shortest paths can be reconstructed. + * + *

    The elements in the maps returned by + * getIncomingEdgeMap are ordered (that is, returned + * by the iterator) by nondecreasing distance from source. + * + * @author Joshua O'Madadhain + * @author Tom Nelson converted to jung2 + * @see DijkstraDistance + */ +public class DijkstraShortestPath extends DijkstraDistance implements ShortestPath +{ + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally if and only if + * cached is true. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + * @param cached specifies whether the results are to be cached + */ + public DijkstraShortestPath(Graph g, Function nev, boolean cached) + { + super(g, nev, cached); + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified graph and the specified method of extracting weights + * from edges, which caches results locally. + * + * @param g the graph on which distances will be calculated + * @param nev the class responsible for returning weights for edges + */ + public DijkstraShortestPath(Graph g, Function nev) + { + super(g, nev); + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + */ + public DijkstraShortestPath(Graph g) + { + super(g); + } + + /** + *

    Creates an instance of DijkstraShortestPath for + * the specified unweighted graph (that is, all weights 1) which + * caches results locally. + * + * @param g the graph on which distances will be calculated + * @param cached specifies whether the results are to be cached + */ + public DijkstraShortestPath(Graph g, boolean cached) + { + super(g, cached); + } + + @Override + protected SourceData getSourceData(V source) + { + SourceData sd = sourceMap.get(source); + if (sd == null) + sd = new SourcePathData(source); + return sd; + } + + /** + *

    Returns the last edge on a shortest path from source + * to target, or null if target is not + * reachable from source. + * + *

    If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + * + * @param source the vertex where the shortest path starts + * @param target the vertex where the shortest path ends + * @return the last edge on a shortest path from {@code source} to {@code target} + * or null if {@code target} is not reachable from {@code source} + */ + public E getIncomingEdge(V source, V target) + { + if (!g.containsVertex(source)) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if (!g.containsVertex(target)) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + + Set targets = new HashSet(); + targets.add(target); + singleSourceShortestPath(source, targets, g.getVertexCount()); + @SuppressWarnings("unchecked") + Map incomingEdgeMap = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + E incomingEdge = incomingEdgeMap.get(target); + + if (!cached) + reset(source); + + return incomingEdge; + } + + /** + *

    Returns a LinkedHashMap which maps each vertex + * in the graph (including the source vertex) + * to the last edge on the shortest path from the + * source vertex. + * The map's iterator will return the elements in order of + * increasing distance from source. + * + * @see DijkstraDistance#getDistanceMap(Object,int) + * @see DijkstraDistance#getDistance(Object,Object) + * @param source the vertex from which distances are measured + */ + public Map getIncomingEdgeMap(V source) + { + return getIncomingEdgeMap(source, g.getVertexCount()); + } + + /** + * Returns a List of the edges on the shortest path from + * source to target, in order of their + * occurrence on this path. + * If either vertex is not in the graph for which this instance + * was created, throws IllegalArgumentException. + * + * @param source the starting vertex for the path to generate + * @param target the ending vertex for the path to generate + * @return the edges on the shortest path from {@code source} to {@code target}, + * in order of their occurrence + */ + public List getPath(V source, V target) + { + if(!g.containsVertex(source)) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if(!g.containsVertex(target)) + throw new IllegalArgumentException("Specified target vertex " + + target + " is not part of graph " + g); + + LinkedList path = new LinkedList(); + + // collect path data; must use internal method rather than + // calling getIncomingEdge() because getIncomingEdge() may + // wipe out results if results are not cached + Set targets = new HashSet(); + targets.add(target); + singleSourceShortestPath(source, targets, g.getVertexCount()); + @SuppressWarnings("unchecked") + Map incomingEdges = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + + if (incomingEdges.isEmpty() || incomingEdges.get(target) == null) + return path; + V current = target; + while (!current.equals(source)) + { + E incoming = incomingEdges.get(current); + path.addFirst(incoming); + current = ((Graph)g).getOpposite(current, incoming); + } + return path; + } + + + /** + *

    Returns a LinkedHashMap which maps each of the closest + * numDests vertices to the source vertex + * in the graph (including the source vertex) + * to the incoming edge along the path from that vertex. Throws + * an IllegalArgumentException if source + * is not in this instance's graph, or if numDests is + * either less than 1 or greater than the number of vertices in the + * graph. + * + * @see #getIncomingEdgeMap(Object) + * @see #getPath(Object,Object) + * @param source the vertex from which distances are measured + * @param numDests the number of vertices for which to measure distances + * @return a map from each of the closest {@code numDests} vertices + * to the last edge on the shortest path to that vertex starting from {@code source} + */ + public LinkedHashMap getIncomingEdgeMap(V source, int numDests) + { + if (g.getVertices().contains(source) == false) + throw new IllegalArgumentException("Specified source vertex " + + source + " is not part of graph " + g); + + if (numDests < 1 || numDests > g.getVertexCount()) + throw new IllegalArgumentException("numDests must be >= 1 " + + "and <= g.numVertices()"); + + singleSourceShortestPath(source, null, numDests); + + @SuppressWarnings("unchecked") + LinkedHashMap incomingEdgeMap = + ((SourcePathData)sourceMap.get(source)).incomingEdges; + + if (!cached) + reset(source); + + return incomingEdgeMap; + } + + + /** + * For a given source vertex, holds the estimated and final distances, + * tentative and final assignments of incoming edges on the shortest path from + * the source vertex, and a priority queue (ordered by estimaed distance) + * of the vertices for which distances are unknown. + * + * @author Joshua O'Madadhain + */ + protected class SourcePathData extends SourceData + { + protected Map tentativeIncomingEdges; + protected LinkedHashMap incomingEdges; + + protected SourcePathData(V source) + { + super(source); + incomingEdges = new LinkedHashMap(); + tentativeIncomingEdges = new HashMap(); + } + + @Override + public void update(V dest, E tentative_edge, double new_dist) + { + super.update(dest, tentative_edge, new_dist); + tentativeIncomingEdges.put(dest, tentative_edge); + } + + @Override + public Map.Entry getNextVertex() + { + Map.Entry p = super.getNextVertex(); + V v = p.getKey(); + E incoming = tentativeIncomingEdges.remove(v); + incomingEdges.put(v, incoming); + return p; + } + + @Override + public void restoreVertex(V v, double dist) + { + super.restoreVertex(v, dist); + E incoming = incomingEdges.get(v); + tentativeIncomingEdges.put(v, incoming); + } + + @Override + public void createRecord(V w, E e, double new_dist) + { + super.createRecord(w, e, new_dist); + tentativeIncomingEdges.put(w, e); + } + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/Distance.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Created on Apr 2, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Map; + + +/** + * An interface for classes which calculate the distance between + * one vertex and another. + * + * @author Joshua O'Madadhain + */ +public interface Distance +{ + /** + * Returns the distance from the source vertex to the + * target vertex. If target is not reachable from + * source, returns null. + * + * @param source the vertex from which distance is to be measured + * @param target the vertex to which distance is to be measured + * @return the distance from {@code source} to {@code target} + */ + Number getDistance(V source, V target); + + /** + * Returns a Map which maps each vertex in the graph (including + * the source vertex) to its distance (represented as a Number) + * from source. If any vertex is not reachable from + * source, no distance is stored for that vertex. + * + * @param source the vertex from which distances are to be measured + * @return a {@code Map} of the distances from {@code source} to other vertices in the graph + */ + Map getDistanceMap(V source); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/DistanceStatistics.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,165 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; +import java.util.Collection; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality; +import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer; +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Statistics relating to vertex-vertex distances in a graph. + * + *

    Formerly known as GraphStatistics in JUNG 1.x. + * + * @author Scott White + * @author Joshua O'Madadhain + */ +public class DistanceStatistics +{ + /** + * For each vertex v in graph, + * calculates the average shortest path length from v + * to all other vertices in graph using the metric + * specified by d, and returns the results in a + * Map from vertices to Double values. + * If there exists an ordered pair <u,v> + * for which d.getDistance(u,v) returns null, + * then the average distance value for u will be stored + * as Double.POSITIVE_INFINITY). + * + *

    Does not include self-distances (path lengths from v + * to v). + * + *

    To calculate the average distances, ignoring edge weights if any: + *

    +     * Map distances = DistanceStatistics.averageDistances(g, new UnweightedShortestPath(g));
    +     * 
    + * To calculate the average distances respecting edge weights: + *
    +     * DijkstraShortestPath dsp = new DijkstraShortestPath(g, nev);
    +     * Map distances = DistanceStatistics.averageDistances(g, dsp);
    +     * 
    + * where nev is an instance of Transformer that + * is used to fetch the weight for each edge. + * + * @see edu.uci.ics.jung.algorithms.shortestpath.UnweightedShortestPath + * @see edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance + * + * @param graph the graph for which distances are to be calculated + * @param d the distance metric to use for the calculation + * @param the vertex type + * @param the edge type + * @return a map from each vertex to the mean distance to each other (reachable) vertex + */ + public static Function averageDistances(Hypergraph graph, Distance d) + { + final ClosenessCentrality cc = new ClosenessCentrality(graph, d); + return new VertexScoreTransformer(cc); + } + + /** + * For each vertex v in g, + * calculates the average shortest path length from v + * to all other vertices in g, ignoring edge weights. + * @see #diameter(Hypergraph) + * @see edu.uci.ics.jung.algorithms.scoring.ClosenessCentrality + * + * @param g the graph for which distances are to be calculated + * @param the vertex type + * @param the edge type + * @return a map from each vertex to the mean distance to each other (reachable) vertex + */ + public static Function averageDistances(Hypergraph g) + { + final ClosenessCentrality cc = new ClosenessCentrality(g, + new UnweightedShortestPath(g)); + return new VertexScoreTransformer(cc); + } + + /** + * Returns the diameter of g using the metric + * specified by d. The diameter is defined to be + * the maximum, over all pairs of vertices u,v, + * of the length of the shortest path from u to + * v. If the graph is disconnected (that is, not + * all pairs of vertices are reachable from one another), the + * value returned will depend on use_max: + * if use_max == true, the value returned + * will be the the maximum shortest path length over all pairs of connected + * vertices; otherwise it will be Double.POSITIVE_INFINITY. + * + * @param g the graph for which distances are to be calculated + * @param d the distance metric to use for the calculation + * @param use_max if {@code true}, return the maximum shortest path length for all graphs; + * otherwise, return {@code Double.POSITIVE_INFINITY} for disconnected graphs + * @param the vertex type + * @param the edge type + * @return the longest distance from any vertex to any other + */ + public static double diameter(Hypergraph g, Distance d, boolean use_max) + { + double diameter = 0; + Collection vertices = g.getVertices(); + for(V v : vertices) { + for(V w : vertices) { + + if (v.equals(w) == false) // don't include self-distances + { + Number dist = d.getDistance(v, w); + if (dist == null) + { + if (!use_max) + return Double.POSITIVE_INFINITY; + } + else + diameter = Math.max(diameter, dist.doubleValue()); + } + } + } + return diameter; + } + + /** + * Returns the diameter of g using the metric + * specified by d. The diameter is defined to be + * the maximum, over all pairs of vertices u,v, + * of the length of the shortest path from u to + * v, or Double.POSITIVE_INFINITY + * if any of these distances do not exist. + * @see #diameter(Hypergraph, Distance, boolean) + * + * @param g the graph for which distances are to be calculated + * @param d the distance metric to use for the calculation + * @param the vertex type + * @param the edge type + * @return the longest distance from any vertex to any other + */ + public static double diameter(Hypergraph g, Distance d) + { + return diameter(g, d, false); + } + + /** + * Returns the diameter of g, ignoring edge weights. + * @see #diameter(Hypergraph, Distance, boolean) + * + * @param g the graph for which distances are to be calculated + * @param the vertex type + * @param the edge type + * @return the longest distance from any vertex to any other + */ + public static double diameter(Hypergraph g) + { + return diameter(g, new UnweightedShortestPath(g)); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest2.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,106 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.cluster.WeakComponentClusterer; +import edu.uci.ics.jung.algorithms.filters.FilterUtils; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +@SuppressWarnings("unchecked") +public class MinimumSpanningForest2 { + + protected Graph graph; + protected Forest forest; + protected Function weights = + (Function)Functions.constant(1.0); + + /** + * Create a Forest from the supplied Graph and supplied Supplier, which + * is used to create a new, empty Forest. If non-null, the supplied root + * will be used as the root of the tree/forest. If the supplied root is + * null, or not present in the Graph, then an arbitary Graph vertex + * will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the graph for which the minimum spanning forest will be generated + * @param supplier a factory for the type of forest to build + * @param treeFactory a factory for the type of tree to build + * @param weights edge weights; may be null + */ + public MinimumSpanningForest2(Graph graph, + Supplier> supplier, + Supplier> treeFactory, + Function weights) { + this(graph, supplier.get(), + treeFactory, + weights); + } + + /** + * Create a forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param treeFactory a factory for the type of tree to build + * @param weights edge weights, may be null + */ + public MinimumSpanningForest2(Graph graph, + Forest forest, + Supplier> treeFactory, + Function weights) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + if(weights != null) { + this.weights = weights; + } + + WeakComponentClusterer wcc = + new WeakComponentClusterer(); + Set> component_vertices = wcc.apply(graph); + Collection> components = + FilterUtils.createAllInducedSubgraphs(component_vertices, graph); + + for(Graph component : components) { + PrimMinimumSpanningTree mst = + new PrimMinimumSpanningTree(treeFactory, this.weights); + Graph subTree = mst.apply(component); + if(subTree instanceof Tree) { + TreeUtils.addSubTree(forest, (Tree)subTree, null, null); + } + } + } + + /** + * @return the generated forest + */ + public Forest getForest() { + return forest; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/MinimumSpanningForest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,163 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class MinimumSpanningForest { + + protected Graph graph; + protected Forest forest; + protected Function weights; + + /** + * Creates a Forest from the supplied Graph and supplied Supplier, which + * is used to create a new, empty Forest. If non-null, the supplied root + * will be used as the root of the tree/forest. If the supplied root is + * null, or not present in the Graph, then an arbitrary Graph vertex + * will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created. + * @param graph the input graph + * @param Supplier the Supplier to use to create the new forest + * @param root the vertex of the graph to be used as the root of the forest + * @param weights edge weights + */ + public MinimumSpanningForest(Graph graph, Supplier> Supplier, + V root, Map weights) { + this(graph, Supplier.get(), root, weights); + } + + /** + * Creates a minimum spanning forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitrary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param root first Tree root, may be null + * @param weights edge weights, may be null + */ + public MinimumSpanningForest(Graph graph, Forest forest, + V root, Map weights) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + if(weights != null) { + this.weights = Functions.forMap(weights); + } + Set unfinishedEdges = new HashSet(graph.getEdges()); + if(graph.getVertices().contains(root)) { + this.forest.addVertex(root); + } + updateForest(forest.getVertices(), unfinishedEdges); + } + + /** + * Creates a minimum spanning forest from the supplied graph, populating the + * supplied Forest, which must be empty. + * If the supplied root is null, or not present in the Graph, + * then an arbitrary Graph vertex will be selected as the root. + * If the Minimum Spanning Tree does not include all vertices of the + * Graph, then a leftover vertex is selected as a root, and another + * tree is created + * @param graph the Graph to find MST in + * @param forest the Forest to populate. Must be empty + * @param root first Tree root, may be null + */ + @SuppressWarnings("unchecked") + public MinimumSpanningForest(Graph graph, Forest forest, + V root) { + + if(forest.getVertexCount() != 0) { + throw new IllegalArgumentException("Supplied Forest must be empty"); + } + this.graph = graph; + this.forest = forest; + this.weights = (Function) Functions.constant(1.0); + Set unfinishedEdges = new HashSet(graph.getEdges()); + if(graph.getVertices().contains(root)) { + this.forest.addVertex(root); + } + updateForest(forest.getVertices(), unfinishedEdges); + } + + /** + * @return the generated forest + */ + public Forest getForest() { + return forest; + } + + protected void updateForest(Collection tv, Collection unfinishedEdges) { + double minCost = Double.MAX_VALUE; + E nextEdge = null; + V nextVertex = null; + V currentVertex = null; + for(E e : unfinishedEdges) { + + if(forest.getEdges().contains(e)) continue; + // find the lowest cost edge, get its opposite endpoint, + // and then update forest from its Successors + Pair endpoints = graph.getEndpoints(e); + V first = endpoints.getFirst(); + V second = endpoints.getSecond(); + if(tv.contains(first) == true && tv.contains(second) == false) { + if(weights.apply(e) < minCost) { + minCost = weights.apply(e); + nextEdge = e; + currentVertex = first; + nextVertex = second; + } + } + if(graph.getEdgeType(e) == EdgeType.UNDIRECTED && + tv.contains(second) == true && tv.contains(first) == false) { + if(weights.apply(e) < minCost) { + minCost = weights.apply(e); + nextEdge = e; + currentVertex = second; + nextVertex = first; + } + } + } + + if(nextVertex != null && nextEdge != null) { + unfinishedEdges.remove(nextEdge); + forest.addEdge(nextEdge, currentVertex, nextVertex); + updateForest(forest.getVertices(), unfinishedEdges); + } + Collection leftovers = new HashSet(graph.getVertices()); + leftovers.removeAll(forest.getVertices()); + if(leftovers.size() > 0) { + V anotherRoot = leftovers.iterator().next(); + forest.addVertex(anotherRoot); + updateForest(forest.getVertices(), unfinishedEdges); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,30 @@ + + + + + + + +Provides interfaces and classes for calculating (geodesic) distances and shortest paths. Currently includes: +
      +
    • DijkstraDistance: finds the distances from a specified source vertex to other vertices in a +weighted graph with no negative cycles +
    • DijkstraShortestPath: extends DijkstraDistance, also finds shortest paths +
    • Distance: an interface for defining vertex-vertex distances +
    • PrimMinimumSpanningTree: identifies the spanning tree for a graph of least total edge weight +
    • ShortestPath: an interface for shortest-path algorithms +
    • ShortestPathUtils: utility functions for manipulating shortest paths +
    • UnweightedShortestPath: finds the distances from a specified source vertex to other vertices in an +unweighted graph +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/PrimMinimumSpanningTree.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,118 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * For the input Graph, creates a MinimumSpanningTree + * using a variation of Prim's algorithm. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class PrimMinimumSpanningTree implements Function,Graph> { + + protected Supplier> treeFactory; + protected Function weights; + + /** + * Creates an instance which generates a minimum spanning tree assuming constant edge weights. + * @param supplier used to create the tree instances + */ + public PrimMinimumSpanningTree(Supplier> supplier) { + this(supplier, Functions.constant(1.0)); + } + + /** + * Creates an instance which generates a minimum spanning tree using the input edge weights. + * @param supplier used to create the tree instances + * @param weights the edge weights to use for defining the MST + */ + public PrimMinimumSpanningTree(Supplier> supplier, + Function weights) { + this.treeFactory = supplier; + if(weights != null) { + this.weights = weights; + } + } + + /** + * @param graph the Graph to find MST in + */ + public Graph apply(Graph graph) { + Set unfinishedEdges = new HashSet(graph.getEdges()); + Graph tree = treeFactory.get(); + V root = findRoot(graph); + if(graph.getVertices().contains(root)) { + tree.addVertex(root); + } else if(graph.getVertexCount() > 0) { + // pick an arbitrary vertex to make root + tree.addVertex(graph.getVertices().iterator().next()); + } + updateTree(tree, graph, unfinishedEdges); + + return tree; + } + + protected V findRoot(Graph graph) { + for(V v : graph.getVertices()) { + if(graph.getInEdges(v).size() == 0) { + return v; + } + } + // if there is no obvious root, pick any vertex + if(graph.getVertexCount() > 0) { + return graph.getVertices().iterator().next(); + } + // this graph has no vertices + return null; + } + + protected void updateTree(Graph tree, Graph graph, Collection unfinishedEdges) { + Collection tv = tree.getVertices(); + double minCost = Double.MAX_VALUE; + E nextEdge = null; + V nextVertex = null; + V currentVertex = null; + for(E e : unfinishedEdges) { + + if(tree.getEdges().contains(e)) continue; + // find the lowest cost edge, get its opposite endpoint, + // and then update forest from its Successors + Pair endpoints = graph.getEndpoints(e); + V first = endpoints.getFirst(); + V second = endpoints.getSecond(); + if((tv.contains(first) == true && tv.contains(second) == false)) { + if(weights.apply(e) < minCost) { + minCost = weights.apply(e); + nextEdge = e; + currentVertex = first; + nextVertex = second; + } + } else if((tv.contains(second) == true && tv.contains(first) == false)) { + if(weights.apply(e) < minCost) { + minCost = weights.apply(e); + nextEdge = e; + currentVertex = second; + nextVertex = first; + } + } + } + + if(nextVertex != null && nextEdge != null) { + unfinishedEdges.remove(nextEdge); + tree.addEdge(nextEdge, currentVertex, nextVertex); + updateTree(tree, graph, unfinishedEdges); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPath.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +* +* Created on Feb 12, 2004 +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.Map; + + +/** + * An interface for algorithms that calculate shortest paths. + */ +public interface ShortestPath +{ + /** + * Returns a map from vertices to the last edge on the shortest path to that vertex + * starting from {@code source}. + * + * @param source the starting point for the shortest paths + * @return a map from vertices to the last edge on the shortest path to that vertex + * starting from {@code source} + */ + Map getIncomingEdgeMap(V source); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/ShortestPathUtils.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Created on Jul 10, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Utilities relating to the shortest paths in a graph. + */ +public class ShortestPathUtils +{ + /** + * Returns a List of the edges on the shortest path from + * source to target, in order of their + * occurrence on this path. + * + * @param graph the graph for which the shortest path is defined + * @param sp holder of the shortest path information + * @param source the vertex from which the shortest path is measured + * @param target the vertex to which the shortest path is measured + * @param the vertex type + * @param the edge type + * @return the edges on the shortest path from {@code source} to {@code target}, + * in the order traversed + */ + public static List getPath(Graph graph, ShortestPath sp, V source, V target) + { + LinkedList path = new LinkedList(); + + Map incomingEdges = sp.getIncomingEdgeMap(source); + + if (incomingEdges.isEmpty() || incomingEdges.get(target) == null) + return path; + V current = target; + while (!current.equals(source)) + { + E incoming = incomingEdges.get(current); + path.addFirst(incoming); + Pair endpoints = graph.getEndpoints(incoming); + if(endpoints.getFirst().equals(current)) { + current = endpoints.getSecond(); + } else { + current = endpoints.getFirst(); + } + } + return path; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/shortestpath/UnweightedShortestPath.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,152 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Computes the shortest path distances for graphs whose edges are not weighted (using BFS). + * + * @author Scott White + */ +public class UnweightedShortestPath + implements ShortestPath, Distance +{ + private Map> mDistanceMap; + private Map> mIncomingEdgeMap; + private Hypergraph mGraph; + private Map distances = new HashMap(); + + /** + * Constructs and initializes algorithm + * @param g the graph + */ + public UnweightedShortestPath(Hypergraph g) + { + mDistanceMap = new HashMap>(); + mIncomingEdgeMap = new HashMap>(); + mGraph = g; + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistance(Object, Object) + */ + public Number getDistance(V source, V target) + { + Map sourceSPMap = getDistanceMap(source); + return sourceSPMap.get(target); + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.Distance#getDistanceMap(Object) + */ + public Map getDistanceMap(V source) + { + Map sourceSPMap = mDistanceMap.get(source); + if (sourceSPMap == null) + { + computeShortestPathsFromSource(source); + sourceSPMap = mDistanceMap.get(source); + } + return sourceSPMap; + } + + /** + * @see edu.uci.ics.jung.algorithms.shortestpath.ShortestPath#getIncomingEdgeMap(Object) + */ + public Map getIncomingEdgeMap(V source) + { + Map sourceIEMap = mIncomingEdgeMap.get(source); + if (sourceIEMap == null) + { + computeShortestPathsFromSource(source); + sourceIEMap = mIncomingEdgeMap.get(source); + } + return sourceIEMap; + } + + + /** + * Computes the shortest path distances from a given node to all other nodes. + * @param source the source node + */ + private void computeShortestPathsFromSource(V source) + { + BFSDistanceLabeler labeler = new BFSDistanceLabeler(); + labeler.labelDistances(mGraph, source); + distances = labeler.getDistanceDecorator(); + Map currentSourceSPMap = new HashMap(); + Map currentSourceEdgeMap = new HashMap(); + + for(V vertex : mGraph.getVertices()) { + + Number distanceVal = distances.get(vertex); + // BFSDistanceLabeler uses -1 to indicate unreachable vertices; + // don't bother to store unreachable vertices + if (distanceVal != null && distanceVal.intValue() >= 0) + { + currentSourceSPMap.put(vertex, distanceVal); + int minDistance = distanceVal.intValue(); + for(E incomingEdge : mGraph.getInEdges(vertex)) + { + for (V neighbor : mGraph.getIncidentVertices(incomingEdge)) + { + if (neighbor.equals(vertex)) + continue; + + Number predDistanceVal = distances.get(neighbor); + + int pred_distance = predDistanceVal.intValue(); + if (pred_distance < minDistance && pred_distance >= 0) + { + minDistance = predDistanceVal.intValue(); + currentSourceEdgeMap.put(vertex, incomingEdge); + } + } + } + } + } + mDistanceMap.put(source, currentSourceSPMap); + mIncomingEdgeMap.put(source, currentSourceEdgeMap); + } + + /** + * Clears all stored distances for this instance. + * Should be called whenever the graph is modified (edge weights + * changed or edges added/removed). If the user knows that + * some currently calculated distances are unaffected by a + * change, reset(V) may be appropriate instead. + * + * @see #reset(Object) + */ + public void reset() + { + mDistanceMap.clear(); + mIncomingEdgeMap.clear(); + } + + /** + * Clears all stored distances for the specified source vertex + * source. Should be called whenever the stored distances + * from this vertex are invalidated by changes to the graph. + * + * @see #reset() + * + * @param v the vertex for which distances should be cleared + */ + public void reset(V v) + { + mDistanceMap.remove(v); + mIncomingEdgeMap.remove(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/DirectionTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Apr 21, 2004 + */ +package edu.uci.ics.jung.algorithms.transformation; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + *

    Functions for transforming graphs into directed or undirected graphs. + * + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class DirectionTransformer +{ + + /** + * Transforms graph (which may be of any directionality) + * into an undirected graph. (This may be useful for + * visualization tasks). + * Specifically: + *

      + *
    • Vertices are copied from graph. + *
    • Directed edges are 'converted' into a single new undirected edge in the new graph. + *
    • Each undirected edge (if any) in graph is 'recreated' with a new undirected edge in the new + * graph if create_new is true, or copied from graph otherwise. + *
    + * + * @param graph the graph to be transformed + * @param create_new specifies whether existing undirected edges are to be copied or recreated + * @param graph_factory used to create the new graph object + * @param edge_factory used to create new edges + * @param the vertex type + * @param the edge type + * @return the transformed Graph + */ + public static UndirectedGraph toUndirected(Graph graph, + Supplier> graph_factory, + Supplier edge_factory, boolean create_new) + { + UndirectedGraph out = graph_factory.get(); + + for (V v : graph.getVertices()) + out.addVertex(v); + + for (E e : graph.getEdges()) + { + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + E to_add; + if (graph.getEdgeType(e) == EdgeType.DIRECTED || create_new) + to_add = edge_factory.get(); + else + to_add = e; + out.addEdge(to_add, v1, v2, EdgeType.UNDIRECTED); + } + return out; + } + + /** + * Transforms graph (which may be of any directionality) + * into a directed graph. + * Specifically: + *
      + *
    • Vertices are copied from graph. + *
    • Undirected edges are 'converted' into two new antiparallel directed edges in the new graph. + *
    • Each directed edge (if any) in graph is 'recreated' with a new edge in the new + * graph if create_new is true, or copied from graph otherwise. + *
    + * + * @param graph the graph to be transformed + * @param create_new specifies whether existing directed edges are to be copied or recreated + * @param graph_factory used to create the new graph object + * @param edge_factory used to create new edges + * @param the vertex type + * @param the edge type + * @return the transformed Graph + */ + public static Graph toDirected(Graph graph, Supplier> graph_factory, + Supplier edge_factory, boolean create_new) + { + DirectedGraph out = graph_factory.get(); + + for (V v : graph.getVertices()) + out.addVertex(v); + + for (E e : graph.getEdges()) + { + Pair endpoints = graph.getEndpoints(e); + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) + { + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + out.addEdge(edge_factory.get(), v1, v2, EdgeType.DIRECTED); + out.addEdge(edge_factory.get(), v2, v1, EdgeType.DIRECTED); + } + else // if the edge is directed, just add it + { + V source = graph.getSource(e); + V dest = graph.getDest(e); + E to_add = create_new ? edge_factory.get() : e; + out.addEdge(to_add, source, dest, EdgeType.DIRECTED); + } + + } + return out; + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/FoldingTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Apr 21, 2004 + */ +package edu.uci.ics.jung.algorithms.transformation; + +import java.util.ArrayList; +import java.util.Collection; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.KPartiteGraph; + +/** + * Methods for creating a "folded" graph based on a k-partite graph or a + * hypergraph. + * + *

    A "folded" graph is derived from a k-partite graph by identifying + * a partition of vertices which will become the vertices of the new graph, copying + * these vertices into the new graph, and then connecting those vertices whose + * original analogues were connected indirectly through elements + * of other partitions. + * + *

    A "folded" graph is derived from a hypergraph by creating vertices based on + * either the vertices or the hyperedges of the original graph, and connecting + * vertices in the new graph if their corresponding vertices/hyperedges share a + * connection with a common hyperedge/vertex. + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +public class FoldingTransformer +{ + + /** + * Converts g into a unipartite graph whose vertex set is the + * vertices of g's partition p. For vertices + * a and b in this partition, the resultant + * graph will include the edge (a,b) if the original graph + * contains edges (a,c) and (c,b) for at least + * one vertex c. + * + *

    The vertices of the new graph are the same as the vertices of the + * appropriate partition in the old graph; the edges in the new graph are + * created by the input edge Factory. + * + *

    If there is more than 1 such vertex c for a given pair + * (a,b), the type of the output graph will determine whether + * it will contain parallel edges or not. + * + *

    This function will not create self-loops. + * + * @param vertex type + * @param input edge type + * @param g input k-partite graph + * @param p predicate specifying vertex partition + * @param graph_factory Supplier used to create the output graph + * @param edge_factory Supplier used to create the edges in the new graph + * @return a copy of the input graph folded with respect to the input partition + */ + public static Graph foldKPartiteGraph(KPartiteGraph g, Predicate p, + Supplier> graph_factory, Supplier edge_factory) + { + Graph newGraph = graph_factory.get(); + + // get vertices for the specified partition + Collection vertices = g.getVertices(p); + for (V v : vertices) + { + newGraph.addVertex(v); + for (V s : g.getSuccessors(v)) + { + for (V t : g.getSuccessors(s)) + { + if (!vertices.contains(t) || t.equals(v)) + continue; + newGraph.addVertex(t); + newGraph.addEdge(edge_factory.get(), v, t); + } + } + } + return newGraph; + } + + /** + * Converts g into a unipartite graph whose vertices are the + * vertices of g's partition p, and whose edges + * consist of collections of the intermediate vertices from other partitions. + * For vertices + * a and b in this partition, the resultant + * graph will include the edge (a,b) if the original graph + * contains edges (a,c) and (c,b) for at least + * one vertex c. + * + *

    The vertices of the new graph are the same as the vertices of the + * appropriate partition in the old graph; the edges in the new graph are + * collections of the intermediate vertices c. + * + *

    This function will not create self-loops. + * + * @param vertex type + * @param input edge type + * @param g input k-partite graph + * @param p predicate specifying vertex partition + * @param graph_factory Supplier used to create the output graph + * @return the result of folding g into unipartite graph whose vertices + * are those of the p partition of g + */ + public static Graph> foldKPartiteGraph(KPartiteGraph g, Predicate p, + Supplier>> graph_factory) + { + Graph> newGraph = graph_factory.get(); + + // get vertices for the specified partition, copy into new graph + Collection vertices = g.getVertices(p); + + for (V v : vertices) + { + newGraph.addVertex(v); + for (V s : g.getSuccessors(v)) + { + for (V t : g.getSuccessors(s)) + { + if (!vertices.contains(t) || t.equals(v)) + continue; + newGraph.addVertex(t); + Collection v_coll = newGraph.findEdge(v, t); + if (v_coll == null) + { + v_coll = new ArrayList(); + newGraph.addEdge(v_coll, v, t); + } + v_coll.add(s); + } + } + } + return newGraph; + } + + /** + * Creates a Graph which is an edge-folded version of h, where + * hyperedges are replaced by k-cliques in the output graph. + * + *

    The vertices of the new graph are the same objects as the vertices of + * h, and a + * is connected to b in the new graph if the corresponding vertices + * in h are connected by a hyperedge. Thus, each hyperedge with + * k vertices in h induces a k-clique in the new graph. + * + *

    The edges of the new graph consist of collections of each hyperedge that connected + * the corresponding vertex pair in the original graph. + * + * @param vertex type + * @param input edge type + * @param h hypergraph to be folded + * @param graph_factory Supplier used to generate the output graph + * @return a copy of the input graph where hyperedges are replaced by cliques + */ + public static Graph> foldHypergraphEdges(Hypergraph h, + Supplier>> graph_factory) + { + Graph> target = graph_factory.get(); + + for (V v : h.getVertices()) + target.addVertex(v); + + for (E e : h.getEdges()) + { + ArrayList incident = new ArrayList(h.getIncidentVertices(e)); + populateTarget(target, e, incident); + } + return target; + } + + + /** + * Creates a Graph which is an edge-folded version of h, where + * hyperedges are replaced by k-cliques in the output graph. + * + *

    The vertices of the new graph are the same objects as the vertices of + * h, and a + * is connected to b in the new graph if the corresponding vertices + * in h are connected by a hyperedge. Thus, each hyperedge with + * k vertices in h induces a k-clique in the new graph. + * + *

    The edges of the new graph are generated by the specified edge Supplier. + * + * @param vertex type + * @param input edge type + * @param h hypergraph to be folded + * @param graph_factory Supplier used to generate the output graph + * @param edge_factory Supplier used to create the new edges + * @return a copy of the input graph where hyperedges are replaced by cliques + */ + public static Graph foldHypergraphEdges(Hypergraph h, + Supplier> graph_factory, Supplier edge_factory) + { + Graph target = graph_factory.get(); + + for (V v : h.getVertices()) + target.addVertex(v); + + for (E e : h.getEdges()) + { + ArrayList incident = new ArrayList(h.getIncidentVertices(e)); + for (int i = 0; i < incident.size(); i++) + for (int j = i+1; j < incident.size(); j++) + target.addEdge(edge_factory.get(), incident.get(i), incident.get(j)); + } + return target; + } + + /** + * Creates a Graph which is a vertex-folded version of h, whose + * vertices are the input's hyperedges and whose edges are induced by adjacent hyperedges + * in the input. + * + *

    The vertices of the new graph are the same objects as the hyperedges of + * h, and a + * is connected to b in the new graph if the corresponding edges + * in h have a vertex in common. Thus, each vertex incident to + * k edges in h induces a k-clique in the new graph. + * + *

    The edges of the new graph are created by the specified Supplier. + * + * @param vertex type + * @param input edge type + * @param output edge type + * @param h hypergraph to be folded + * @param graph_factory Supplier used to generate the output graph + * @param edge_factory Supplier used to generate the output edges + * @return a transformation of the input graph whose vertices correspond to the input's hyperedges + * and edges are induced by hyperedges sharing vertices in the input + */ + public static Graph foldHypergraphVertices(Hypergraph h, + Supplier> graph_factory, Supplier edge_factory) + { + Graph target = graph_factory.get(); + + for (E e : h.getEdges()) + target.addVertex(e); + + for (V v : h.getVertices()) + { + ArrayList incident = new ArrayList(h.getIncidentEdges(v)); + for (int i = 0; i < incident.size(); i++) + for (int j = i+1; j < incident.size(); j++) + target.addEdge(edge_factory.get(), incident.get(i), incident.get(j)); + } + + return target; + } + + /** + * Creates a Graph which is a vertex-folded version of h, whose + * vertices are the input's hyperedges and whose edges are induced by adjacent hyperedges + * in the input. + * + *

    The vertices of the new graph are the same objects as the hyperedges of + * h, and a + * is connected to b in the new graph if the corresponding edges + * in h have a vertex in common. Thus, each vertex incident to + * k edges in h induces a k-clique in the new graph. + * + *

    The edges of the new graph consist of collections of each vertex incident to + * the corresponding hyperedge pair in the original graph. + * + * @param h hypergraph to be folded + * @param graph_factory Supplier used to generate the output graph + * @return a transformation of the input graph whose vertices correspond to the input's hyperedges + * and edges are induced by hyperedges sharing vertices in the input + */ + public Graph> foldHypergraphVertices(Hypergraph h, + Supplier>> graph_factory) + { + Graph> target = graph_factory.get(); + + for (E e : h.getEdges()) + target.addVertex(e); + + for (V v : h.getVertices()) + { + ArrayList incident = new ArrayList(h.getIncidentEdges(v)); + populateTarget(target, v, incident); + } + return target; + } + + /** + * @param target + * @param e + * @param incident + */ + private static void populateTarget(Graph> target, T e, + ArrayList incident) + { + for (int i = 0; i < incident.size(); i++) + { + S v1 = incident.get(i); + for (int j = i+1; j < incident.size(); j++) + { + S v2 = incident.get(j); + Collection e_coll = target.findEdge(v1, v2); + if (e_coll == null) + { + e_coll = new ArrayList(); + target.addEdge(e_coll, v1, v2); + } + e_coll.add(e); + } + } + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ + + + + + + + +Mechanisms for graph transformation. These currently include: +

      +
    • DirectionTransformer: generates graphs where input undirected +edges have been converted to directed edges, or vice versa +
    • FoldingTransformer: transforms k-partite graphs or hypergraphs +into unipartite graphs +
    • VertexPartitionCollapser: transforms a graph, given a +partition of its vertices into disjoint sets, into a graph in which each +of these disjoint sets has been 'collapsed' into a single new vertex. +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/transformation/VertexPartitionCollapser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.transformation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.blockmodel.VertexPartition; +import edu.uci.ics.jung.graph.Graph; + +/** + * This class transforms a graph with a known vertex partitioning into a graph whose + * vertices correspond to the input graph's partitions. Two vertices in the output graph + * are connected if and only if there exists at least one edge between vertices in the + * corresponding partitions of the input graph. If the output graph permits parallel edges, + * there will be an edge connecting two vertices in the new graph for each such + * edge connecting constituent vertices in the input graph. + * + *

    Concept based on Danyel Fisher's GraphCollapser in JUNG 1.x. + * + */ +public class VertexPartitionCollapser +{ + protected Supplier> graph_factory; + protected Supplier vertex_factory; + protected Supplier edge_factory; + protected Map, CV> set_collapsedv; + + /** + * Creates an instance with the specified graph and element factories. + * @param vertex_factory used to construct the vertices of the new graph + * @param edge_factory used to construct the edges of the new graph + * @param graph_factory used to construct the new graph + */ + public VertexPartitionCollapser(Supplier> graph_factory, + Supplier vertex_factory, Supplier edge_factory) + { + this.graph_factory = graph_factory; + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + this.set_collapsedv = new HashMap, CV>(); + } + + /** + * Creates a new graph whose vertices correspond to the partitions of the supplied graph. + * @param partitioning a vertex partition of a graph + * @return a new graph whose vertices correspond to the partitions of the supplied graph + */ + public Graph collapseVertexPartitions(VertexPartition partitioning) + { + Graph original = partitioning.getGraph(); + Graph collapsed = graph_factory.get(); + + // create vertices in new graph corresponding to equivalence sets in the original graph + for (Set set : partitioning.getVertexPartitions()) + { + CV cv = vertex_factory.get(); + collapsed.addVertex(vertex_factory.get()); + set_collapsedv.put(set, cv); + } + + // create edges in new graph corresponding to edges in original graph + for (E e : original.getEdges()) + { + Collection incident = original.getIncidentVertices(e); + Collection collapsed_vertices = new HashSet(); + Map> vertex_partitions = partitioning.getVertexToPartitionMap(); + // collect the collapsed vertices corresponding to the original incident vertices + for (V v : incident) + collapsed_vertices.add(set_collapsedv.get(vertex_partitions.get(v))); + // if there's only one collapsed vertex, continue (no edges to create) + if (collapsed_vertices.size() > 1) + { + CE ce = edge_factory.get(); + collapsed.addEdge(ce, collapsed_vertices); + } + } + return collapsed; + } + + /** + * @return a Function from vertex sets in the original graph to collapsed vertices + * in the transformed graph. + */ + public Function, CV> getSetToCollapsedVertexTransformer() + { + return Functions.forMap(set_collapsedv); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/BasicMapEntry.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,81 @@ +package edu.uci.ics.jung.algorithms.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * An simple minimal implementation of Map.Entry. + * + * @param the key type + * @param the value type + */ +public class BasicMapEntry implements Map.Entry { + final K key; + V value; + + /** + * @param k the key + * @param v the value + */ + public BasicMapEntry(K k, V v) { + value = v; + key = k; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V newValue) { + V oldValue = value; + value = newValue; + return oldValue; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Map.Entry)) + return false; + @SuppressWarnings("rawtypes") + Map.Entry e = (Map.Entry)o; + Object k1 = getKey(); + Object k2 = e.getKey(); + if (k1 == k2 || (k1 != null && k1.equals(k2))) { + Object v1 = getValue(); + Object v2 = e.getValue(); + if (v1 == v2 || (v1 != null && v1.equals(v2))) + return true; + } + return false; + } + + @Override + public int hashCode() { + return (key==null ? 0 : key.hashCode()) ^ + (value==null ? 0 : value.hashCode()); + } + + @Override + public String toString() { + return getKey() + "=" + getValue(); + } + + /** + * This method is invoked whenever the value in an entry is + * overwritten by an invocation of put(k,v) for a key k that's already + * in the HashMap. + */ + void recordAccess(HashMap m) { + } + + /** + * This method is invoked whenever the entry is + * removed from the table. + */ + void recordRemoval(HashMap m) { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/DiscreteDistribution.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Feb 18, 2004 + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Collection; +import java.util.Iterator; + +import com.google.common.base.Preconditions; + +/** + * A utility class for calculating properties of discrete distributions. + * Generally, these distributions are represented as arrays of + * double values, which are assumed to be normalized + * such that the entries in a single array sum to 1. + * + * @author Joshua O'Madadhain + */ +public class DiscreteDistribution +{ + + /** + * Returns the Kullback-Leibler divergence between the + * two specified distributions, which must have the same + * number of elements. This is defined as + * the sum over all i of + * dist[i] * Math.log(dist[i] / reference[i]). + * Note that this value is not symmetric; see + * symmetricKL for a symmetric variant. + * @see #symmetricKL(double[], double[]) + * @param dist the distribution whose divergence from {@code reference} is being measured + * @param reference the reference distribution + * @return sum_i of {@code dist[i] * Math.log(dist[i] / reference[i])} + */ + public static double KullbackLeibler(double[] dist, double[] reference) + { + double distance = 0; + + Preconditions.checkArgument(dist.length == reference.length, + "input arrays must be of the same length"); + + for (int i = 0; i < dist.length; i++) + { + if (dist[i] > 0 && reference[i] > 0) + distance += dist[i] * Math.log(dist[i] / reference[i]); + } + return distance; + } + + /** + * @param dist the distribution whose divergence from {@code reference} is being measured + * @param reference the reference distribution + * @return KullbackLeibler(dist, reference) + KullbackLeibler(reference, dist) + * @see #KullbackLeibler(double[], double[]) + */ + public static double symmetricKL(double[] dist, double[] reference) + { + return KullbackLeibler(dist, reference) + + KullbackLeibler(reference, dist); + } + + /** + * Returns the squared difference between the + * two specified distributions, which must have the same + * number of elements. This is defined as + * the sum over all i of the square of + * (dist[i] - reference[i]). + * @param dist the distribution whose distance from {@code reference} is being measured + * @param reference the reference distribution + * @return sum_i {@code (dist[i] - reference[i])^2} + */ + public static double squaredError(double[] dist, double[] reference) + { + double error = 0; + + Preconditions.checkArgument(dist.length == reference.length, + "input arrays must be of the same length"); + + for (int i = 0; i < dist.length; i++) + { + double difference = dist[i] - reference[i]; + error += difference * difference; + } + return error; + } + + /** + * Returns the cosine distance between the two + * specified distributions, which must have the same number + * of elements. The distributions are treated as vectors + * in dist.length-dimensional space. + * Given the following definitions + *

      + *
    • v = the sum over all i of dist[i] * dist[i] + *
    • w = the sum over all i of reference[i] * reference[i] + *
    • vw = the sum over all i of dist[i] * reference[i] + *
    + * the value returned is defined as vw / (Math.sqrt(v) * Math.sqrt(w)). + * @param dist the distribution whose distance from {@code reference} is being measured + * @param reference the reference distribution + * @return the cosine distance between {@code dist} and {@code reference}, considered as vectors + */ + public static double cosine(double[] dist, double[] reference) + { + double v_prod = 0; // dot product x*x + double w_prod = 0; // dot product y*y + double vw_prod = 0; // dot product x*y + + Preconditions.checkArgument(dist.length == reference.length, + "input arrays must be of the same length"); + + for (int i = 0; i < dist.length; i++) + { + vw_prod += dist[i] * reference[i]; + v_prod += dist[i] * dist[i]; + w_prod += reference[i] * reference[i]; + } + // cosine distance between v and w + return vw_prod / (Math.sqrt(v_prod) * Math.sqrt(w_prod)); + } + + /** + * Returns the entropy of this distribution. + * High entropy indicates that the distribution is + * close to uniform; low entropy indicates that the + * distribution is close to a Dirac delta (i.e., if + * the probability mass is concentrated at a single + * point, this method returns 0). Entropy is defined as + * the sum over all i of + * -(dist[i] * Math.log(dist[i])) + * + * @param dist the distribution whose entropy is being measured + * @return sum_i {@code -(dist[i] * Math.log(dist[i]))} + */ + public static double entropy(double[] dist) + { + double total = 0; + + for (int i = 0; i < dist.length; i++) + { + if (dist[i] > 0) + total += dist[i] * Math.log(dist[i]); + } + return -total; + } + + /** + * Normalizes, with Lagrangian smoothing, the specified double + * array, so that the values sum to 1 (i.e., can be treated as probabilities). + * The effect of the Lagrangian smoothing is to ensure that all entries + * are nonzero; effectively, a value of alpha is added to each + * entry in the original array prior to normalization. + * @param counts the array to be converted into a probability distribution + * @param alpha the value to add to each entry prior to normalization + */ + public static void normalize(double[] counts, double alpha) + { + double total_count = 0; + + for (int i = 0; i < counts.length; i++) + total_count += counts[i]; + + for (int i = 0; i < counts.length; i++) + counts[i] = (counts[i] + alpha) + / (total_count + counts.length * alpha); + } + + /** + * Returns the mean of the specified Collection of + * distributions, which are assumed to be normalized arrays of + * double values. + * @see #mean(double[][]) + * @param distributions the distributions whose mean is to be calculated + * @return the mean of the distributions + */ + public static double[] mean(Collection distributions) + { + if (distributions.isEmpty()) + throw new IllegalArgumentException("Distribution collection must be non-empty"); + Iterator iter = distributions.iterator(); + double[] first = iter.next(); + double[][] d_array = new double[distributions.size()][first.length]; + d_array[0] = first; + for (int i = 1; i < d_array.length; i++) + d_array[i] = iter.next(); + + return mean(d_array); + } + + /** + * Returns the mean of the specified array of distributions, + * represented as normalized arrays of double values. + * Will throw an "index out of bounds" exception if the + * distribution arrays are not all of the same length. + * @param distributions the distributions whose mean is to be calculated + * @return the mean of the distributions + */ + public static double[] mean(double[][] distributions) + { + double[] d_mean = new double[distributions[0].length]; + for (int j = 0; j < d_mean.length; j++) + d_mean[j] = 0; + + for (int i = 0; i < distributions.length; i++) + for (int j = 0; j < d_mean.length; j++) + d_mean[j] += distributions[i][j] / distributions.length; + + return d_mean; + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/Indexer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Collection; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +/** + * A class providing static methods useful for improving the + * performance of graph algorithms. + * + * @author Tom Nelson + * + */ +public class Indexer { + + /** + * Returns a BiMap mapping each element of the collection to its + * index as encountered while iterating over the collection. The purpose + * of the index operation is to supply an O(1) replacement operation for the + * O(n) indexOf(element) method of a List + * @param the type of the collection elements + * @param collection the collection whose indices are to be generated + * @return a bidirectional map from collection elements to 0-based indices + */ + public static BiMap create(Collection collection) { + return create(collection, 0); + } + /** + * Returns a BiMap mapping each element of the collection to its + * index as encountered while iterating over the collection. The purpose + * of the index operation is to supply an O(1) replacement operation for the + * O(n) indexOf(element) method of a List + * @param the type of the collection elements + * @param collection the collection whose indices are to be generated + * @param start start index + * @return a bidirectional map from collection elements to start-based indices + */ + public static BiMap create(Collection collection, int start) { + BiMap map = HashBiMap.create(); + int i=start; + for(T t : collection) { + map.put(t,i++); + } + return map; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeContext.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + + +/** + * An interface for algorithms that proceed iteratively. + * + */ +public interface IterativeContext +{ + /** + * Advances one step. + */ + void step(); + + /** + * @return {@code true} if this iterative process is finished, and {@code false} otherwise. + */ + boolean done(); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/IterativeProcess.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,174 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.util; + + + +/** + * Provides basic infrastructure for iterative algorithms. Services provided include: + *
      + *
    • storage of current and max iteration count
    • + *
    • framework for initialization, iterative evaluation, and finalization
    • + *
    • test for convergence
    • + *
    • etc.
    • + *
    + *

    + * Algorithms that subclass this class are typically used in the following way:
    + *

    + * FooAlgorithm foo = new FooAlgorithm(...)
    + * foo.setMaximumIterations(100); //set up conditions
    + * ...
    + * foo.evaluate(); //key method which initiates iterative process
    + * foo.getSomeResult();
    + * 
    + * + * @author Scott White (originally written by Didier Besset) + */ +public abstract class IterativeProcess implements IterativeContext { + /** + * Number of iterations performed. + */ + private int iterations; + /** + * Maximum allowed number of iterations. + */ + private int maximumIterations = 50; + /** + * Desired precision. + */ + private double desiredPrecision = Double.MIN_VALUE; + /** + * Achieved precision. + */ + private double precision; + + + /** + * Generic constructor. + */ + public IterativeProcess() { + } + + /** + * Performs the iterative process. + * Note: this method does not return anything because Java does not + * allow mixing double, int, or objects + */ + public void evaluate() { + iterations = 0; + initializeIterations(); + while (iterations++ < maximumIterations) { + step(); + precision = getPrecision(); + if (hasConverged()) + break; + } + finalizeIterations(); + } + + /** + * Evaluate the result of the current iteration. + */ + abstract public void step(); + + /** + * Perform eventual clean-up operations + * (must be implement by subclass when needed). + */ + protected void finalizeIterations() { + } + + /** + * @return the desired precision. + */ + public double getDesiredPrecision() { + return desiredPrecision; + } + + /** + * @return the number of iterations performed. + */ + public int getIterations() { + return iterations; + } + + /** + * @return the maximum allowed number of iterations. + */ + public int getMaximumIterations() { + return maximumIterations; + } + + /** + * @return the attained precision. + */ + public double getPrecision() { + return precision; + } + + /** + * @param precision the precision to set + */ + public void setPrecision(double precision) { + this.precision = precision; + } + + /** + * + * Check to see if the result has been attained. + * @return boolean + */ + public boolean hasConverged() { + return precision < desiredPrecision; + } + + public boolean done() { + return hasConverged(); + } + + /** + * Initializes internal parameters to start the iterative process. + */ + protected void initializeIterations() { + } + + /** + * + */ + public void reset() { + } + + /** + * @return double + * @param epsilon double + * @param x double + */ + public double relativePrecision(double epsilon, double x) { + return x > desiredPrecision ? epsilon / x: epsilon; + } + + /** + * @param prec the desired precision. + */ + public void setDesiredPrecision(double prec) throws IllegalArgumentException { + if (prec <= 0) + throw new IllegalArgumentException("Non-positive precision: " + prec); + desiredPrecision = prec; + } + + /** + * @param maxIter the maximum allowed number of iterations + */ + public void setMaximumIterations(int maxIter) throws IllegalArgumentException { + if (maxIter < 1) + throw new IllegalArgumentException("Non-positive maximum iteration: " + maxIter); + maximumIterations = maxIter; + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/KMeansClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Aug 9, 2004 + * + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Random; +import java.util.Set; + + + +/** + * Groups items into a specified number of clusters, based on their proximity in + * d-dimensional space, using the k-means algorithm. Calls to + * cluster will terminate when either of the two following + * conditions is true: + *
      + *
    • the number of iterations is > max_iterations + *
    • none of the centroids has moved as much as convergence_threshold + * since the previous iteration + *
    + * + * @author Joshua O'Madadhain + */ +public class KMeansClusterer +{ + protected int max_iterations; + protected double convergence_threshold; + protected Random rand; + + /** + * Creates an instance which will terminate when either the maximum number of + * iterations has been reached, or all changes are smaller than the convergence threshold. + * @param max_iterations the maximum number of iterations to employ + * @param convergence_threshold the smallest change we want to track + */ + public KMeansClusterer(int max_iterations, double convergence_threshold) + { + this.max_iterations = max_iterations; + this.convergence_threshold = convergence_threshold; + this.rand = new Random(); + } + + /** + * Creates an instance with max iterations of 100 and convergence threshold + * of 0.001. + */ + public KMeansClusterer() + { + this(100, 0.001); + } + + /** + * @return the maximum number of iterations + */ + public int getMaxIterations() + { + return max_iterations; + } + + /** + * @param max_iterations the maximum number of iterations + */ + public void setMaxIterations(int max_iterations) + { + if (max_iterations < 0) + throw new IllegalArgumentException("max iterations must be >= 0"); + + this.max_iterations = max_iterations; + } + + /** + * @return the convergence threshold + */ + public double getConvergenceThreshold() + { + return convergence_threshold; + } + + /** + * @param convergence_threshold the convergence threshold + */ + public void setConvergenceThreshold(double convergence_threshold) + { + if (convergence_threshold <= 0) + throw new IllegalArgumentException("convergence threshold " + + "must be > 0"); + + this.convergence_threshold = convergence_threshold; + } + + /** + * Returns a Collection of clusters, where each cluster is + * represented as a Map of Objects to locations + * in d-dimensional space. + * @param object_locations a map of the items to cluster, to + * double arrays that specify their locations in d-dimensional space. + * @param num_clusters the number of clusters to create + * @return a clustering of the input objects in d-dimensional space + * @throws NotEnoughClustersException if {@code num_clusters} is larger than the number of + * distinct points in object_locations + */ + @SuppressWarnings("unchecked") + public Collection> cluster(Map object_locations, int num_clusters) + { + if (object_locations == null || object_locations.isEmpty()) + throw new IllegalArgumentException("'objects' must be non-empty"); + + if (num_clusters < 2 || num_clusters > object_locations.size()) + throw new IllegalArgumentException("number of clusters " + + "must be >= 2 and <= number of objects (" + + object_locations.size() + ")"); + + + Set centroids = new HashSet(); + + Object[] obj_array = object_locations.keySet().toArray(); + Set tried = new HashSet(); + + // create the specified number of clusters + while (centroids.size() < num_clusters && tried.size() < object_locations.size()) + { + T o = (T)obj_array[(int)(rand.nextDouble() * obj_array.length)]; + tried.add(o); + double[] mean_value = object_locations.get(o); + boolean duplicate = false; + for (double[] cur : centroids) + { + if (Arrays.equals(mean_value, cur)) + duplicate = true; + } + if (!duplicate) + centroids.add(mean_value); + } + + if (tried.size() >= object_locations.size()) + throw new NotEnoughClustersException(); + + // put items in their initial clusters + Map> clusterMap = assignToClusters(object_locations, centroids); + + // keep reconstituting clusters until either + // (a) membership is stable, or + // (b) number of iterations passes max_iterations, or + // (c) max movement of any centroid is <= convergence_threshold + int iterations = 0; + double max_movement = Double.POSITIVE_INFINITY; + while (iterations++ < max_iterations && max_movement > convergence_threshold) + { + max_movement = 0; + Set new_centroids = new HashSet(); + // calculate new mean for each cluster + for (Map.Entry> entry : clusterMap.entrySet()) + { + double[] centroid = entry.getKey(); + Map elements = entry.getValue(); + ArrayList locations = new ArrayList(elements.values()); + + double[] mean = DiscreteDistribution.mean(locations); + max_movement = Math.max(max_movement, + Math.sqrt(DiscreteDistribution.squaredError(centroid, mean))); + new_centroids.add(mean); + } + + // TODO: check membership of clusters: have they changed? + + // regenerate cluster membership based on means + clusterMap = assignToClusters(object_locations, new_centroids); + } + return clusterMap.values(); + } + + /** + * Assigns each object to the cluster whose centroid is closest to the + * object. + * @param object_locations a map of objects to locations + * @param centroids the centroids of the clusters to be formed + * @return a map of objects to assigned clusters + */ + protected Map> assignToClusters(Map object_locations, Set centroids) + { + Map> clusterMap = new HashMap>(); + for (double[] centroid : centroids) + clusterMap.put(centroid, new HashMap()); + + for (Map.Entry object_location : object_locations.entrySet()) + { + T object = object_location.getKey(); + double[] location = object_location.getValue(); + + // find the cluster with the closest centroid + Iterator c_iter = centroids.iterator(); + double[] closest = c_iter.next(); + double distance = DiscreteDistribution.squaredError(location, closest); + + while (c_iter.hasNext()) + { + double[] centroid = c_iter.next(); + double dist_cur = DiscreteDistribution.squaredError(location, centroid); + if (dist_cur < distance) + { + distance = dist_cur; + closest = centroid; + } + } + clusterMap.get(closest).put(object, location); + } + + return clusterMap; + } + + /** + * Sets the seed used by the internal random number generator. + * Enables consistent outputs. + * @param random_seed the random seed to use + */ + public void setSeed(int random_seed) + { + this.rand = new Random(random_seed); + } + + /** + * An exception that indicates that the specified data points cannot be + * clustered into the number of clusters requested by the user. + * This will happen if and only if there are fewer distinct points than + * requested clusters. (If there are fewer total data points than + * requested clusters, IllegalArgumentException will be thrown.) + * + * @author Joshua O'Madadhain + */ + @SuppressWarnings("serial") + public static class NotEnoughClustersException extends RuntimeException + { + @Override + public String getMessage() + { + return "Not enough distinct points in the input data set to form " + + "the requested number of clusters"; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapBinaryHeap.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * + * Created on Oct 29, 2003 + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.Vector; + +import com.google.common.collect.Iterators; + +/** + * An array-based binary heap implementation of a priority queue, + * which also provides + * efficient update() and contains operations. + * It contains extra infrastructure (a hash table) to keep track of the + * position of each element in the array; thus, if the key value of an element + * changes, it may be "resubmitted" to the heap via update + * so that the heap can reposition it efficiently, as necessary. + * + * @author Joshua O'Madadhain + */ +public class MapBinaryHeap + extends AbstractCollection + implements Queue +{ + private Vector heap = new Vector(); // holds the heap as an implicit binary tree + private Map object_indices = new HashMap(); // maps each object in the heap to its index in the heap + private Comparator comp; + private final static int TOP = 0; // the index of the top of the heap + + /** + * Creates a MapBinaryHeap whose heap ordering + * is based on the ordering of the elements specified by comp. + * @param comp the comparator to use to order elements in the heap + */ + public MapBinaryHeap(Comparator comp) + { + initialize(comp); + } + + /** + * Creates a MapBinaryHeap whose heap ordering + * will be based on the natural ordering of the elements, + * which must be Comparable. + */ + public MapBinaryHeap() + { + initialize(new ComparableComparator()); + } + + /** + * Creates a MapBinaryHeap based on the specified + * collection whose heap ordering + * will be based on the natural ordering of the elements, + * which must be Comparable. + * @param c the collection of {@code Comparable} elements to add to the heap + */ + public MapBinaryHeap(Collection c) + { + this(); + addAll(c); + } + + /** + * Creates a MapBinaryHeap based on the specified collection + * whose heap ordering + * is based on the ordering of the elements specified by c. + * @param c the collection of elements to add to the heap + * @param comp the comparator to use for items in {@code c} + */ + public MapBinaryHeap(Collection c, Comparator comp) + { + this(comp); + addAll(c); + } + + private void initialize(Comparator comp) + { + this.comp = comp; + clear(); + } + + /** + * @see Collection#clear() + */ + @Override + public void clear() + { + object_indices.clear(); + heap.clear(); + } + + /** + * Inserts o into this collection. + */ + @Override + public boolean add(T o) + { + int i = heap.size(); // index 1 past the end of the heap + heap.setSize(i+1); + percolateUp(i, o); + return true; + } + + /** + * Returns true if this collection contains no elements, and + * false otherwise. + */ + @Override + public boolean isEmpty() + { + return heap.isEmpty(); + } + + /** + * Returns the element at the top of the heap; does not + * alter the heap. + */ + public T peek() + { + if (heap.size() > 0) + return heap.elementAt(TOP); + else + return null; + } + + /** + * @return the size of this heap + */ + @Override + public int size() + { + return heap.size(); + } + + /** + * Informs the heap that this object's internal key value has been + * updated, and that its place in the heap may need to be shifted + * (up or down). + * @param o the object whose key value has been updated + */ + public void update(T o) + { + // Since we don't know whether the key value increased or + // decreased, we just percolate up followed by percolating down; + // one of the two will have no effect. + + int cur = object_indices.get(o).intValue(); // current index + int new_idx = percolateUp(cur, o); + percolateDown(new_idx); + } + + @Override + public boolean contains(Object o) + { + return object_indices.containsKey(o); + } + + /** + * Moves the element at position cur closer to + * the bottom of the heap, or returns if no further motion is + * necessary. Calls itself recursively if further motion is + * possible. + */ + private void percolateDown(int cur) + { + int left = lChild(cur); + int right = rChild(cur); + int smallest; + + if ((left < heap.size()) && + (comp.compare(heap.elementAt(left), heap.elementAt(cur)) < 0)) { + smallest = left; + } else { + smallest = cur; + } + + if ((right < heap.size()) && + (comp.compare(heap.elementAt(right), heap.elementAt(smallest)) < 0)) { + smallest = right; + } + + if (cur != smallest) + { + swap(cur, smallest); + percolateDown(smallest); + } + } + + /** + * Moves the element o at position cur + * as high as it can go in the heap. Returns the new position of the + * element in the heap. + */ + private int percolateUp(int cur, T o) + { + int i = cur; + + while ((i > TOP) && (comp.compare(heap.elementAt(parent(i)), o) > 0)) + { + T parentElt = heap.elementAt(parent(i)); + heap.setElementAt(parentElt, i); + object_indices.put(parentElt, new Integer(i)); // reset index to i (new location) + i = parent(i); + } + + // place object in heap at appropriate place + object_indices.put(o, new Integer(i)); + heap.setElementAt(o, i); + + return i; + } + + /** + * Returns the index of the left child of the element at + * index i of the heap. + * @param i + * @return the index of the left child of the element at + * index i of the heap + */ + private int lChild(int i) + { + return (i<<1) + 1; + } + + /** + * Returns the index of the right child of the element at + * index i of the heap. + * @param i + * @return the index of the right child of the element at + * index i of the heap + */ + private int rChild(int i) + { + return (i<<1) + 2; + } + + /** + * Returns the index of the parent of the element at + * index i of the heap. + * @param i + * @return the index of the parent of the element at index i of the heap + */ + private int parent(int i) + { + return (i-1)>>1; + } + + /** + * Swaps the positions of the elements at indices i + * and j of the heap. + * @param i + * @param j + */ + private void swap(int i, int j) + { + T iElt = heap.elementAt(i); + T jElt = heap.elementAt(j); + + heap.setElementAt(jElt, i); + object_indices.put(jElt, new Integer(i)); + + heap.setElementAt(iElt, j); + object_indices.put(iElt, new Integer(j)); + } + + /** + * Comparator used if none is specified in the constructor. + * @author Joshua O'Madadhain + */ + private class ComparableComparator implements Comparator + { + /** + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @SuppressWarnings("unchecked") + public int compare(T arg0, T arg1) + { + if (!(arg0 instanceof Comparable) || !(arg1 instanceof Comparable)) + throw new IllegalArgumentException("Arguments must be Comparable"); + + return ((Comparable)arg0).compareTo(arg1); + } + } + + /** + * Returns an Iterator that does not support modification + * of the heap. + */ + @Override + public Iterator iterator() + { + return Iterators.unmodifiableIterator(heap.iterator()); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean remove(Object o) + { + throw new UnsupportedOperationException(); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean removeAll(Collection c) + { + throw new UnsupportedOperationException(); + } + + /** + * This data structure does not support the removal of arbitrary elements. + */ + @Override + public boolean retainAll(Collection c) + { + throw new UnsupportedOperationException(); + } + + public T element() throws NoSuchElementException + { + T top = this.peek(); + if (top == null) + throw new NoSuchElementException(); + return top; + } + + public boolean offer(T o) + { + return add(o); + } + + public T poll() + { + T top = this.peek(); + if (top != null) + { + T bottom_elt = heap.lastElement(); + heap.setElementAt(bottom_elt, TOP); + object_indices.put(bottom_elt, new Integer(TOP)); + + heap.setSize(heap.size() - 1); // remove the last element + if (heap.size() > 1) + percolateDown(TOP); + + object_indices.remove(top); + } + return top; + } + + public T remove() + { + T top = this.poll(); + if (top == null) + throw new NoSuchElementException(); + return top; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/MapSettableTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Created on Aug 5, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Map; + + +/** + * A SettableTransformer that operates on an underlying Map instance. + * Similar to MapTransformer. + * + * @author Joshua O'Madadhain + */ +public class MapSettableTransformer implements SettableTransformer +{ + protected Map map; + + /** + * Creates an instance based on m. + * @param m the map on which this instance is based + */ + public MapSettableTransformer(Map m) + { + this.map = m; + } + + public O apply(I input) + { + return map.get(input); + } + + public void set(I input, O output) + { + map.put(input, output); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/package.html libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/package.html --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + +Provides general algorithmic utilities. These include: +
      +
    • DiscreteDistribution: calculates statistical measures on +discrete probability distributions represented as double arrays +
    • KMeansClusterer: uses the k-means algorithm to cluster +points in d-dimensional space into k clusters +
    • MapBinaryHeap: a binary heap implementation that permits +efficient element access and update operations +
    • RandomLocationTransformer: a class that randomly assigns +2D coordinates to items (default initializer for iterative Layouts) +
    • SettableTransformer: an extension of Transformer +that allows mutation of the transformation +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SelfLoopEdgePredicate.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,23 @@ +package edu.uci.ics.jung.algorithms.util; + +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * A Predicate that returns true if the input edge's + * endpoints in the input graph are identical. (Thus, an edge which connects + * its sole incident vertex to itself). + * + * @param the vertex type + * @param the edge type + */ +public class SelfLoopEdgePredicate implements Predicate,E>> { + + public boolean apply(Context,E> context) { + Pair endpoints = context.graph.getEndpoints(context.element); + return endpoints.getFirst().equals(endpoints.getSecond()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/SettableTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Created on Aug 5, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.util; + +import com.google.common.base.Function; + +/** + * An interface for classes that can set the value to be returned (from transform()) + * when invoked on a given input. + * + * @author Joshua O'Madadhain + */ +public interface SettableTransformer extends Function +{ + /** + * Sets the value (output) to be returned by a call to + * transform(input)). + * @param input the value whose output value is being specified + * @param output the output value for {@code input} + */ + public void set(I input, O output); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/util/WeightedChoice.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2009, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jan 8, 2009 + * + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Random; + +/** + * Selects items according to their probability in an arbitrary probability + * distribution. The distribution is specified by a {@code Map} from + * items (of type {@code T}) to weights of type {@code Number}, supplied + * to the constructor; these weights are normalized internally to act as + * probabilities. + * + *

    This implementation selects items in O(1) time, and requires O(n) space. + * + * @author Joshua O'Madadhain + */ +public class WeightedChoice +{ + private List item_pairs; + private Random random; + + /** + * The default minimum value that is treated as a valid probability + * (as opposed to rounding error from floating-point operations). + */ + public static final double DEFAULT_THRESHOLD = 0.00000000001; + + /** + * Equivalent to {@code this(item_weights, new Random(), DEFAULT_THRESHOLD)}. + * @param item_weights a map from items to their weights + */ + public WeightedChoice(Map item_weights) + { + this(item_weights, new Random(), DEFAULT_THRESHOLD); + } + + /** + * Equivalent to {@code this(item_weights, new Random(), threshold)}. + * @param item_weights a map from items to their weights + * @param threshold the minimum value that is treated as a probability + * (anything smaller will be considered equivalent to a floating-point rounding error) + */ + public WeightedChoice(Map item_weights, double threshold) + { + this(item_weights, new Random(), threshold); + } + + /** + * Equivalent to {@code this(item_weights, random, DEFAULT_THRESHOLD)}. + * @param item_weights a map from items to their weights + * @param random the Random instance to use for selection + */ + public WeightedChoice(Map item_weights, Random random) + { + this(item_weights, random, DEFAULT_THRESHOLD); + } + + /** + * Creates an instance with the specified mapping from items to weights, + * random number generator, and threshold value. + * + *

    The mapping defines the weight for each item to be selected; this + * will be proportional to the probability of its selection. + *

    The random number generator specifies the mechanism which will be + * used to provide uniform integer and double values. + *

    The threshold indicates default minimum value that is treated as a valid + * probability (as opposed to rounding error from floating-point operations). + * @param item_weights a map from items to their weights + * @param random the Random instance to use for selection + * @param threshold the minimum value that is treated as a probability + * (anything smaller will be considered equivalent to a floating-point rounding error) + */ + public WeightedChoice(Map item_weights, Random random, + double threshold) + { + if (item_weights.isEmpty()) + throw new IllegalArgumentException("Item weights must be non-empty"); + + int item_count = item_weights.size(); + item_pairs = new ArrayList(item_count); + + double sum = 0; + for (Map.Entry entry : item_weights.entrySet()) + { + double value = entry.getValue().doubleValue(); + if (value <= 0) + throw new IllegalArgumentException("Weights must be > 0"); + sum += value; + } + double bucket_weight = 1.0 / item_weights.size(); + + Queue light_weights = new LinkedList(); + Queue heavy_weights = new LinkedList(); + for (Map.Entry entry : item_weights.entrySet()) + { + double value = entry.getValue().doubleValue() / sum; + enqueueItem(entry.getKey(), value, bucket_weight, light_weights, heavy_weights); + } + + // repeat until both queues empty + while (!heavy_weights.isEmpty() || !light_weights.isEmpty()) + { + ItemPair heavy_item = heavy_weights.poll(); + ItemPair light_item = light_weights.poll(); + double light_weight = 0; + T light = null; + T heavy = null; + if (light_item != null) + { + light_weight = light_item.weight; + light = light_item.light; + } + if (heavy_item != null) + { + heavy = heavy_item.heavy; + // put the 'left over' weight from the heavy item--what wasn't + // needed to make up the difference between the light weight and + // 1/n--back in the appropriate queue + double new_weight = heavy_item.weight - (bucket_weight - light_weight); + if (new_weight > threshold) + enqueueItem(heavy, new_weight, bucket_weight, light_weights, heavy_weights); + } + light_weight *= item_count; + + item_pairs.add(new ItemPair(light, heavy, light_weight)); + } + + this.random = random; + } + + /** + * Adds key/value to the appropriate queue. Keys with values less than + * the threshold get added to {@code light_weights}, all others get added + * to {@code heavy_weights}. + */ + private void enqueueItem(T key, double value, double threshold, + Queue light_weights, Queue heavy_weights) + { + if (value < threshold) + light_weights.offer(new ItemPair(key, null, value)); + else + heavy_weights.offer(new ItemPair(null, key, value)); + } + + /** + * @param seed the seed to be used by the internal random number generator + */ + public void setRandomSeed(long seed) + { + this.random.setSeed(seed); + } + + /** + * Retrieves an item with probability proportional to its weight in the + * {@code Map} provided in the input. + * @return an item chosen randomly based on its specified weight + */ + public T nextItem() + { + ItemPair item_pair = item_pairs.get(random.nextInt(item_pairs.size())); + if (random.nextDouble() < item_pair.weight) + return item_pair.light; + return item_pair.heavy; + } + + /** + * Manages light object/heavy object/light conditional probability tuples. + */ + private class ItemPair + { + T light; + T heavy; + double weight; + + private ItemPair(T light, T heavy, double weight) + { + this.light = light; + this.heavy = heavy; + this.weight = weight; + } + + @Override + public String toString() + { + return String.format("[L:%s, H:%s, %.3f]", light, heavy, weight); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/site/site.xml libjung-free-java-2.1.1/jung-algorithms/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + +

    + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestBicomponentClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestBicomponentClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestBicomponentClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestBicomponentClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,268 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + + +/** + * @author Scott White + */ +public class TestBicomponentClusterer extends TestCase { + public static Test suite() { + return new TestSuite(TestBicomponentClusterer.class); + } + + @Override + protected void setUp() { + + } + + public void testExtract0() throws Exception + { + UndirectedGraph graph = new UndirectedSparseMultigraph(); + String[] v = {"0"}; + graph.addVertex(v[0]); + + List> c = new ArrayList>(); + c.add(0, new HashSet()); + c.get(0).add(v[0]); + +// Set[] c = {new HashSet()}; + +// c[0].add(v[0]); + + testComponents(graph, v, c); + } + + public void testExtractEdge() throws Exception + { + UndirectedGraph graph = new UndirectedSparseMultigraph(); + String[] v = {"0","1"}; + graph.addVertex(v[0]); + graph.addVertex(v[1]); + graph.addEdge(0, v[0], v[1]); + + List> c = new ArrayList>(); + c.add(0, new HashSet()); + c.get(0).add(v[0]); + c.get(0).add(v[1]); + +// Set[] c = {new HashSet()}; +// +// c[0].add(v[0]); +// c[0].add(v[1]); + + testComponents(graph, v, c); + } + + public void testExtractV() throws Exception + { + UndirectedGraph graph = new UndirectedSparseMultigraph(); + String[] v = new String[3]; + for (int i = 0; i < 3; i++) + { + v[i] = ""+i; + graph.addVertex(v[i]); + } + graph.addEdge(0, v[0], v[1]); + graph.addEdge(1, v[0], v[2]); + + List> c = new ArrayList>(); + c.add(0, new HashSet()); + c.add(1, new HashSet()); + + c.get(0).add(v[0]); + c.get(0).add(v[1]); + + c.get(1).add(v[0]); + c.get(1).add(v[2]); + +// Set[] c = {new HashSet(), new HashSet()}; +// +// c[0].add(v[0]); +// c[0].add(v[1]); +// +// c[1].add(v[0]); +// c[1].add(v[2]); + + testComponents(graph, v, c); + } + + public void createEdges(String[] v, int[][] edge_array, Graph g) + { + for (int k = 0; k < edge_array.length; k++) + { + int i = edge_array[k][0]; + int j = edge_array[k][1]; + String v1 = getVertex(v, i, g); + String v2 = getVertex(v, j, g); + + g.addEdge(k, v1, v2); + } + } + + public String getVertex(String[] v_array, int i, Graph g) + { + String v = v_array[i]; + if (v == null) + { + v_array[i] = Character.toString((char)('0'+i)); + g.addVertex(v_array[i]); + v = v_array[i]; + } + return v; + } + + public void testExtract1() { + String[] v = new String[6]; + int[][] edges1 = {{0,1}, {0,5}, {0,3}, {0,4}, {1,5}, {3,4}, {2,3}}; + UndirectedGraph graph = new UndirectedSparseMultigraph(); + createEdges(v, edges1, graph); + + List> c = new ArrayList>(); + for (int i = 0; i < 3; i++) + c.add(i, new HashSet()); + + c.get(0).add(v[0]); + c.get(0).add(v[1]); + c.get(0).add(v[5]); + + c.get(1).add(v[0]); + c.get(1).add(v[3]); + c.get(1).add(v[4]); + + c.get(2).add(v[2]); + c.get(2).add(v[3]); + +// Set[] c = new Set[3]; +// for (int i = 0; i < c.length; i++) +// c[i] = new HashSet(); +// +// c[0].add(v[0]); +// c[0].add(v[1]); +// c[0].add(v[5]); +// +// c[1].add(v[0]); +// c[1].add(v[3]); +// c[1].add(v[4]); +// +// c[2].add(v[2]); +// c[2].add(v[3]); + + testComponents(graph, v, c); + } + + public void testExtract2() { + String[] v = new String[9]; + int[][] edges1 = {{0,2}, {0,4}, {1,0}, {2,1}, {3,0}, {4,3}, {5,3}, {6,7}, {6,8}, {8,7}}; + UndirectedGraph graph = new UndirectedSparseMultigraph(); + createEdges(v, edges1, graph); + + List> c = new ArrayList>(); + for (int i = 0; i < 4; i++) + c.add(i, new HashSet()); + + c.get(0).add(v[0]); + c.get(0).add(v[1]); + c.get(0).add(v[2]); + + c.get(1).add(v[0]); + c.get(1).add(v[3]); + c.get(1).add(v[4]); + + c.get(2).add(v[5]); + c.get(2).add(v[3]); + + c.get(3).add(v[6]); + c.get(3).add(v[7]); + c.get(3).add(v[8]); + +// Set[] c = new Set[4]; +// for (int i = 0; i < c.length; i++) +// c[i] = new HashSet(); +// +// c[0].add(v[0]); +// c[0].add(v[1]); +// c[0].add(v[2]); +// +// c[1].add(v[0]); +// c[1].add(v[3]); +// c[1].add(v[4]); +// +// c[2].add(v[5]); +// c[2].add(v[3]); +// +// c[3].add(v[6]); +// c[3].add(v[7]); +// c[3].add(v[8]); + + testComponents(graph, v, c); + } + + public void testComponents(UndirectedGraph graph, String[] vertices, List> c) + { + BicomponentClusterer finder = new BicomponentClusterer(); + Set> bicomponents = finder.apply(graph); + + // check number of components + assertEquals(bicomponents.size(), c.size()); + + // diagnostic; should be commented out for typical unit tests +// for (int i = 0; i < bicomponents.size(); i++) +// { +// System.out.print("Component " + i + ": "); +// Set bicomponent = bicomponents.getCluster(i); +// for (Iterator iter = bicomponent.iterator(); iter.hasNext(); ) +// { +// Vertex w = (Vertex)iter.next(); +// System.out.print(sl.getLabel(w) + " "); +// } +// System.out.println(); +// } +// System.out.println(); + + // make sure that each set in c[] is found in bicomponents + List> clusterList = new ArrayList>(bicomponents); + boolean found = false; + for (int i = 0; i < c.size(); i++) + { + for (int j = 0; j < bicomponents.size(); j++) + if (clusterList.get(j).equals(c.get(i))) + { + found = true; + break; + } + assertTrue(found); + } + + // make sure that each vertex is represented in >=1 element of bicomponents + Set collapsedSet = new HashSet(); + for(Set set : bicomponents) { + collapsedSet.addAll(set); + } + for (String v : graph.getVertices()) + { + assertTrue(collapsedSet.contains(v)); +// assertFalse(((LinkedHashSet)vset).get(v).isEmpty()); + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestEdgeBetweennessClusterer.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestEdgeBetweennessClusterer.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestEdgeBetweennessClusterer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/TestEdgeBetweennessClusterer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.cluster; + +import java.util.Collection; +import java.util.Set; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; + + +/** + * @author Scott White + */ +public class TestEdgeBetweennessClusterer extends TestCase { + public static Test suite() { + return new TestSuite(TestEdgeBetweennessClusterer.class); + } + Supplier> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + + @Override + protected void setUp() { + graphFactory = new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + vertexFactory = new Supplier() { + int n = 0; + public Integer get() { return n++; } + }; + edgeFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + + } + + public void testRanker() { + + Graph graph = new SparseMultigraph(); + for(int i=0; i<10; i++) { + graph.addVertex(i+1); + } + int j=0; + graph.addEdge(j++,1,2); + graph.addEdge(j++,1,3); + graph.addEdge(j++,2,3); + graph.addEdge(j++,5,6); + graph.addEdge(j++,5,7); + graph.addEdge(j++,6,7); + graph.addEdge(j++,8,10); + graph.addEdge(j++,7,8); + graph.addEdge(j++,7,10); + graph.addEdge(j++,3,4); + graph.addEdge(j++,4,6); + graph.addEdge(j++,4,8); + + Assert.assertEquals(graph.getVertexCount(),10); + Assert.assertEquals(graph.getEdgeCount(),12); + + EdgeBetweennessClusterer clusterer = new EdgeBetweennessClusterer(3); + Collection> clusters = clusterer.apply(graph); + + Assert.assertEquals(clusters.size(),3); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClustererTest.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClustererTest.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClustererTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/cluster/WeakComponentClustererTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ +package edu.uci.ics.jung.algorithms.cluster; + +import junit.framework.TestCase; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; + +public class WeakComponentClustererTest extends TestCase { + + Graph graph = TestGraphs.getDemoGraph(); + + public void testWeakComponent() { + WeakComponentClusterer clusterer = + new WeakComponentClusterer(); +// Set> clusterSet = + clusterer.apply(graph); +// System.err.println("set is "+clusterSet); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/filters/impl/TestKNeighborhoodFilter.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/filters/impl/TestKNeighborhoodFilter.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/filters/impl/TestKNeighborhoodFilter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/filters/impl/TestKNeighborhoodFilter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,62 @@ +package edu.uci.ics.jung.algorithms.filters.impl; + +/** + * @author Tom Nelson + */ + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.algorithms.filters.Filter; +import edu.uci.ics.jung.algorithms.filters.KNeighborhoodFilter; +import edu.uci.ics.jung.algorithms.filters.KNeighborhoodFilter.EdgeType; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; + + +public class TestKNeighborhoodFilter extends TestCase { + + DirectedGraph graph; + + public static Test suite() { + return new TestSuite(TestKNeighborhoodFilter.class); + } + + @Override + protected void setUp() { + graph = new DirectedSparseMultigraph(); + for(int i=0; i<7; i++) { + graph.addVertex(i); + } + int j=0; + graph.addEdge(j++, 0, 1); + graph.addEdge(j++, 0, 2); + graph.addEdge(j++, 2, 3); + graph.addEdge(j++, 2, 4); + graph.addEdge(j++, 3, 5); + graph.addEdge(j++, 5, 6); + graph.addEdge(j++, 5, 0); + graph.addEdge(j++, 3, 0); + graph.addEdge(j++, 6, 7); + } + + public void testIn() { + Filter filter = new KNeighborhoodFilter(0, 2, EdgeType.IN); + Graph result = filter.apply(graph); + assertEquals(result.getVertexCount(), 4); + assertEquals(result.getEdgeCount(), 5); + } + public void testOut() { + Filter filter = new KNeighborhoodFilter(0, 2, EdgeType.OUT); + Graph result = filter.apply(graph); + assertEquals(result.getVertexCount(), 5); + assertEquals(result.getEdgeCount(), 5); + } + public void testInOut() { + Filter filter = new KNeighborhoodFilter(0, 2, EdgeType.IN_OUT); + Graph result = filter.apply(graph); + assertEquals(result.getVertexCount(), 7); + assertEquals(result.getEdgeCount(), 8); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/flows/TestEdmondsKarpMaxFlow.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/flows/TestEdmondsKarpMaxFlow.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/flows/TestEdmondsKarpMaxFlow.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/flows/TestEdmondsKarpMaxFlow.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,211 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.flows; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * @author Scott White, Joshua O'Madadhain, Tom Nelson + */ +public class TestEdmondsKarpMaxFlow extends TestCase { + + public static Test suite() { + return new TestSuite(TestEdmondsKarpMaxFlow.class); + } + + @Override + protected void setUp() { + + } + + public void testSanityChecks() + { + DirectedGraph g = new DirectedSparseMultigraph(); + Number source = new Integer(1); + Number sink = new Integer(2); + g.addVertex(source); + g.addVertex(sink); + + Number v = new Integer(3); + + DirectedGraph h = new DirectedSparseMultigraph(); + Number w = new Integer(4); + g.addVertex(w); + + try + { + new EdmondsKarpMaxFlow(g, source, source, null, null, null); + fail("source and sink vertices not distinct"); + } + catch (IllegalArgumentException iae) {} + + try + { + new EdmondsKarpMaxFlow(h, source, w, null, null, null); + fail("source and sink vertices not both part of specified graph"); + } + catch (IllegalArgumentException iae) {} + + try + { + new EdmondsKarpMaxFlow(g, source, v, null, null, null); + fail("source and sink vertices not both part of specified graph"); + } + catch (IllegalArgumentException iae) {} + } + + public void testSimpleFlow() { + DirectedGraph graph = new DirectedSparseMultigraph(); + Supplier edgeFactory = new Supplier() { + int count = 0; + public Number get() { + return count++; + } + }; + + Map edgeCapacityMap = new HashMap(); + for(int i=0; i<6; i++) { + graph.addVertex(i); + } + + Map edgeFlowMap = new HashMap(); + + graph.addEdge(edgeFactory.get(),0,1,EdgeType.DIRECTED); + edgeCapacityMap.put(0, 16); + + graph.addEdge(edgeFactory.get(),0,2,EdgeType.DIRECTED); + edgeCapacityMap.put(1,13); + + graph.addEdge(edgeFactory.get(),1,2,EdgeType.DIRECTED); + edgeCapacityMap.put(2, 6); + + graph.addEdge(edgeFactory.get(),1,3,EdgeType.DIRECTED); + edgeCapacityMap.put(3, 12); + + graph.addEdge(edgeFactory.get(),2,4,EdgeType.DIRECTED); + edgeCapacityMap.put(4, 14); + + graph.addEdge(edgeFactory.get(),3,2,EdgeType.DIRECTED); + edgeCapacityMap.put(5, 9); + + graph.addEdge(edgeFactory.get(),3,5,EdgeType.DIRECTED); + edgeCapacityMap.put(6, 20); + + graph.addEdge(edgeFactory.get(),4,3,EdgeType.DIRECTED); + edgeCapacityMap.put(7, 7); + + graph.addEdge(edgeFactory.get(),4,5,EdgeType.DIRECTED); + edgeCapacityMap.put(8, 4); + + EdmondsKarpMaxFlow ek = + new EdmondsKarpMaxFlow( + graph, + 0, + 5, + Functions.forMap(edgeCapacityMap, null), + edgeFlowMap, + edgeFactory); + ek.evaluate(); + + assertTrue(ek.getMaxFlow() == 23); + Set nodesInS = ek.getNodesInSourcePartition(); + assertEquals(4,nodesInS.size()); + + for (Number v : nodesInS) { + Assert.assertTrue(v.intValue() != 3 && v.intValue() != 5); + } + + Set nodesInT = ek.getNodesInSinkPartition(); + assertEquals(2,nodesInT.size()); + + for (Number v : nodesInT) { + Assert.assertTrue(v.intValue() == 3 || v.intValue() == 5); + } + + Set minCutEdges = ek.getMinCutEdges(); + int maxFlow = 0; + for (Number e : minCutEdges) { + Number flow = edgeFlowMap.get(e); + maxFlow += flow.intValue(); + } + Assert.assertEquals(23,maxFlow); + Assert.assertEquals(3,minCutEdges.size()); + } + + public void testAnotherSimpleFlow() { + DirectedGraph graph = new DirectedSparseMultigraph(); + Supplier edgeFactory = new Supplier() { + int count=0; + public Number get() { + return count++; + } + }; + + Map edgeCapacityMap = new HashMap(); + for(int i=0; i<6; i++) { + graph.addVertex(i); + } + + Map edgeFlowMap = new HashMap(); + + graph.addEdge(edgeFactory.get(),0,1,EdgeType.DIRECTED); + edgeCapacityMap.put(0,5); + + graph.addEdge(edgeFactory.get(),0,2,EdgeType.DIRECTED); + edgeCapacityMap.put(1,3); + + graph.addEdge(edgeFactory.get(),1,5,EdgeType.DIRECTED); + edgeCapacityMap.put(2,2); + + graph.addEdge(edgeFactory.get(),1,2,EdgeType.DIRECTED); + edgeCapacityMap.put(3,8); + + graph.addEdge(edgeFactory.get(),2,3,EdgeType.DIRECTED); + edgeCapacityMap.put(4,4); + + graph.addEdge(edgeFactory.get(),2,4,EdgeType.DIRECTED); + edgeCapacityMap.put(5,2); + + graph.addEdge(edgeFactory.get(),3,4,EdgeType.DIRECTED); + edgeCapacityMap.put(6,3); + + graph.addEdge(edgeFactory.get(),3,5,EdgeType.DIRECTED); + edgeCapacityMap.put(7,6); + + graph.addEdge(edgeFactory.get(),4,5,EdgeType.DIRECTED); + edgeCapacityMap.put(8,1); + + EdmondsKarpMaxFlow ek = + new EdmondsKarpMaxFlow( + graph, + 0, + 5, + Functions.forMap(edgeCapacityMap, null), + edgeFlowMap, + edgeFactory); + ek.evaluate(); + + assertTrue(ek.getMaxFlow() == 7); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestBarabasiAlbert.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestBarabasiAlbert.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestBarabasiAlbert.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestBarabasiAlbert.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2016, the JUNG Project and the Regents of the University + * of California. All rights reserved. + * + * This software is open-source under the BSD license; see + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.algorithms.generators.random; + +import java.util.HashSet; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseGraph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.UndirectedSparseGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * @author W. Giordano + * @author Scott White + * @author James Marchant + */ +public class TestBarabasiAlbert extends TestCase { + protected Supplier> graphFactory; + protected Supplier vertexFactory; + protected Supplier edgeFactory; + + protected int init_vertices = 1; + protected int edges_to_add_per_timestep = 1; + protected int random_seed = 0; + protected int num_timesteps = 10; + protected int num_tests = 10; + + public static Test suite() { + return new TestSuite(TestBarabasiAlbert.class); + } + + @Override + protected void setUp() { + graphFactory = new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + vertexFactory = new Supplier() { + int count; + + public Integer get() { + return count++; + } + }; + edgeFactory = new Supplier() { + int count; + + public Number get() { + return count++; + } + }; + } + + private Graph generateAndTestSizeOfBarabasiAlbertGraph( + Supplier> graphFactory, Supplier vertexFactory, + Supplier edgeFactory, int init_vertices, int edges_to_add_per_timestep, int random_seed, + int num_tests) { + BarabasiAlbertGenerator generator = new BarabasiAlbertGenerator(graphFactory, + vertexFactory, edgeFactory, init_vertices, edges_to_add_per_timestep, random_seed, + new HashSet()); + + Graph graph = null; + // test the graph size over {@code num_tests} intervals of {@code + // num_timesteps} timesteps + for (int i = 1; i <= num_tests; i++) { + generator.evolveGraph(num_timesteps); + graph = generator.get(); + assertEquals(graph.getVertexCount(), (i * num_timesteps) + init_vertices); + assertEquals(graph.getEdgeCount(), edges_to_add_per_timestep * (i * num_timesteps)); + } + + return graph; + } + + public void testMultigraphCreation() { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testDirectedMultigraphCreation() { + graphFactory = new Supplier>() { + public Graph get() { + return new DirectedSparseMultigraph(); + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testUndirectedMultigraphCreation() { + graphFactory = new Supplier>() { + public Graph get() { + return new UndirectedSparseMultigraph(); + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testGraphCreation() { + graphFactory = new Supplier>() { + public Graph get() { + return new SparseGraph(); + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testDirectedGraphCreation() { + graphFactory = new Supplier>() { + public Graph get() { + return new DirectedSparseGraph(); + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testUndirectedGraphCreation() { + graphFactory = new Supplier>() { + public Graph get() { + return new UndirectedSparseGraph(); + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + /** + * Due to the way the Barabasi-Albert algorithm works there should be no + * opportunities for the generation of self-loops within the graph. + */ + public void testNoSelfLoops() { + graphFactory = new Supplier>() { + public Graph get() { + return new UndirectedSparseGraph() { + private static final long serialVersionUID = 1L; + + /** + * This anonymous class works as an UndirectedSparseGraph + * but will not accept edges that connect a vertex to + * itself. + */ + @Override + public boolean addEdge(Number edge, Pair endpoints, EdgeType edgeType) { + if (endpoints == null) + throw new IllegalArgumentException("endpoints may not be null"); + + Integer v1 = endpoints.getFirst(); + Integer v2 = endpoints.getSecond(); + + if (v1.equals(v2)) + throw new IllegalArgumentException("No self-loops"); + else + return super.addEdge(edge, endpoints, edgeType); + } + }; + } + }; + + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, + edges_to_add_per_timestep, random_seed, num_tests); + } + + public void testPreconditions() { + // test init_vertices = 0 + try { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, 0, + edges_to_add_per_timestep, random_seed, num_tests); + fail(); + } catch (IllegalArgumentException e) { + } + + // test negative init_vertices + try { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, -1, + edges_to_add_per_timestep, random_seed, num_tests); + fail(); + } catch (IllegalArgumentException e) { + } + + // test edges_to_add_per_timestep = 0 + try { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, 0, + random_seed, num_tests); + fail(); + } catch (IllegalArgumentException e) { + } + + // test negative edges_to_add_per_timestep + try { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, init_vertices, -1, + random_seed, num_tests); + fail(); + } catch (IllegalArgumentException e) { + } + + // test edges_to_add_per_timestep > init_vertices + try { + generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, edgeFactory, 2, 3, random_seed, + num_tests); + fail(); + } catch (IllegalArgumentException e) { + } + } + + /** + * Every node should have an out-degree AT LEAST equal to the number of + * edges added per timestep (dependent on if it is directed or undirected). + */ + public void testEveryNodeHasCorrectMinimumNumberOfEdges() { + Graph graph = generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, + edgeFactory, init_vertices, edges_to_add_per_timestep, random_seed, num_tests); + + for (Integer v : graph.getVertices()) { + assertTrue(graph.outDegree(v) >= edges_to_add_per_timestep); + } + } + + /** + * Check that not every edge goes to one node; the in-degree of any node + * should be strictly less than the number of edges. + */ + public void testNotEveryEdgeToOneNode() { + Graph graph = generateAndTestSizeOfBarabasiAlbertGraph(graphFactory, vertexFactory, + edgeFactory, init_vertices, edges_to_add_per_timestep, random_seed, num_tests); + + for (Integer v : graph.getVertices()) { + assertTrue(graph.inDegree(v) < graph.getEdgeCount()); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestEppsteinPowerLawGenerator.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestEppsteinPowerLawGenerator.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestEppsteinPowerLawGenerator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestEppsteinPowerLawGenerator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.generators.random; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; + +/** + * @author Scott White + */ +public class TestEppsteinPowerLawGenerator extends TestCase { + + Supplier> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + + public static Test suite() { + return new TestSuite(TestEppsteinPowerLawGenerator.class); + } + + @Override + protected void setUp() { + graphFactory = new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + vertexFactory = new Supplier() { + int count; + public Integer get() { + return count++; + } + }; + edgeFactory = + new Supplier() { + int count; + public Number get() { + return count++; + } + }; + } + + public void testSimpleDirectedCase() { + + for (int r=0; r<10; r++) { + EppsteinPowerLawGenerator generator = + new EppsteinPowerLawGenerator(graphFactory, vertexFactory, edgeFactory, 10,40,r); + generator.setSeed(2); + + Graph graph = generator.get(); + Assert.assertEquals(graph.getVertexCount(),10); + Assert.assertEquals(graph.getEdgeCount(),40); + } + + } + + // TODO: convert what is needed for this test +// public void testPowerLawProperties() { +// +// //long start = System.currentTimeMillis(); +// EppsteinPowerLawGenerator generator = new EppsteinPowerLawGenerator(vertexFactory, edgeFactory, +// 500,1500,100000); +// generator.setSeed(5); +// Graph graph = (Graph) generator.generateGraph(); +// //long stop = System.currentTimeMillis(); +// //System.out.println((stop-start)/1000l); +// +// DoubleArrayList degreeList = DegreeDistributions.getOutdegreeValues(graph.getVertices()); +// int maxDegree = (int) Descriptive.max(degreeList); +// Histogram degreeHistogram = GraphStatistics.createHistogram(degreeList,0,maxDegree,1); +// //for (int index=0;index degreeHistogram.binHeight(2) + degreeHistogram.binHeight(3)); +// +// generator = new EppsteinPowerLawGenerator(500,1500,0); +// graph = (Graph) generator.generateGraph(); +// degreeList = DegreeDistributions.getOutdegreeValues(graph.getVertices()); +// maxDegree = (int) Descriptive.max(degreeList); +// degreeHistogram = GraphStatistics.createHistogram(degreeList,0,maxDegree,1); +// //for (int index=0;index> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + + public static Test suite() { + return new TestSuite(TestErdosRenyi.class); + } + + @Override + protected void setUp() { + graphFactory = new Supplier>() { + public UndirectedGraph get() { + return new UndirectedSparseMultigraph(); + } + }; + vertexFactory = new Supplier() { + int count; + public String get() { + return Character.toString((char)('A'+count++)); + } + }; + edgeFactory = + new Supplier() { + int count; + public Number get() { + return count++; + } + }; + } + + public void test() { + + int numVertices = 100; + int total = 0; + for (int i = 1; i <= 10; i++) { + ErdosRenyiGenerator generator = + new ErdosRenyiGenerator(graphFactory, vertexFactory, edgeFactory, + numVertices,0.1); + generator.setSeed(0); + + Graph graph = generator.get(); + Assert.assertTrue(graph.getVertexCount() == numVertices); + total += graph.getEdgeCount(); + } + total /= 10.0; + Assert.assertTrue(total > 495-50 && total < 495+50); + + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestKleinberg.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestKleinberg.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestKleinberg.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/random/TestKleinberg.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,39 @@ +package edu.uci.ics.jung.algorithms.generators.random; + + +import junit.framework.Assert; +import edu.uci.ics.jung.algorithms.generators.Lattice2DGenerator; +import edu.uci.ics.jung.algorithms.generators.TestLattice2D; +import edu.uci.ics.jung.graph.Graph; + + +/** + * + * @author Joshua O'Madadhain + */ +public class TestKleinberg extends TestLattice2D { + + @Override + protected Lattice2DGenerator generate(int i, int j, int k) + { + return new KleinbergSmallWorldGenerator( + k == 0 ? undirectedGraphFactory : directedGraphFactory, + vertexFactory, edgeFactory, + i, // rows + i, // columns + 0.1, // clustering exponent + j == 0 ? true : false); // toroidal? + } + + @Override + protected void checkEdgeCount(Lattice2DGenerator generator, + Graph graph) + + { + Assert.assertEquals( + generator.getGridEdgeCount() + + ((KleinbergSmallWorldGenerator)generator).getConnectionCount() + * graph.getVertexCount(), + graph.getEdgeCount()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/TestLattice2D.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/TestLattice2D.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/TestLattice2D.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/generators/TestLattice2D.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,87 @@ +package edu.uci.ics.jung.algorithms.generators; + + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + + +public class TestLattice2D extends TestCase { + + protected Supplier> undirectedGraphFactory; + protected Supplier> directedGraphFactory; + protected Supplier vertexFactory; + protected Supplier edgeFactory; + + @Override + protected void setUp() { + undirectedGraphFactory = new Supplier>() { + public UndirectedGraph get() { + return new UndirectedSparseMultigraph(); + } + }; + directedGraphFactory = new Supplier>() { + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + + vertexFactory = new Supplier() { + int count; + public String get() { + return Character.toString((char)('A'+count++)); + } + }; + edgeFactory = + new Supplier() { + int count; + public Number get() { + return count++; + } + }; + } + + public void testCreateSingular() + { + try + { + generate(1, 0, 0); + fail("Did not reject lattice of size < 2"); + } + catch (IllegalArgumentException iae) {} + } + + public void testget() { + for (int i = 3; i <= 10; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + Lattice2DGenerator generator = generate(i, j, k); + Graph graph = generator.get(); + Assert.assertEquals(i*i, graph.getVertexCount()); + checkEdgeCount(generator, graph); + } + } + } + } + + protected Lattice2DGenerator generate(int i, int j, int k) + { + return new Lattice2DGenerator( + k == 0 ? undirectedGraphFactory : directedGraphFactory, + vertexFactory, edgeFactory, + i, j == 0 ? true : false); // toroidal? + } + + protected void checkEdgeCount(Lattice2DGenerator generator, + Graph graph) + { + Assert.assertEquals(generator.getGridEdgeCount(), graph.getEdgeCount()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestBetweennessCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestBetweennessCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestBetweennessCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestBetweennessCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,119 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseGraph; + +/** + * @author Scott White + */ +public class TestBetweennessCentrality extends TestCase { + public static Test suite() { + return new TestSuite(TestBetweennessCentrality.class); + } + + @Override + protected void setUp() {} + +// private static E getEdge(Graph g, int v1Index, int v2Index, BidiMap id) { +// V v1 = id.getKey(v1Index); +// V v2 = id.getKey(v2Index); +// return g.findEdge(v1, v2); +// } + + public void testRanker() { + UndirectedGraph graph = + new UndirectedSparseGraph(); + for(int i=0; i<9; i++) { + graph.addVertex(i); + } + + int edge = 0; + graph.addEdge(edge++, 0,1); + graph.addEdge(edge++, 0,6); + graph.addEdge(edge++, 1,2); + graph.addEdge(edge++, 1,3); + graph.addEdge(edge++, 2,4); + graph.addEdge(edge++, 3,4); + graph.addEdge(edge++, 4,5); + graph.addEdge(edge++, 5,8); + graph.addEdge(edge++, 7,8); + graph.addEdge(edge++, 6,7); + + BetweennessCentrality bc = + new BetweennessCentrality(graph); + bc.setRemoveRankScoresOnFinalize(false); + bc.evaluate(); + +// System.out.println("ranking"); +// for (int i = 0; i < 9; i++) +// System.out.println(String.format("%d: %f", i, bc.getVertexRankScore(i))); + + Assert.assertEquals(bc.getVertexRankScore(0)/28.0,0.2142,.001); + Assert.assertEquals(bc.getVertexRankScore(1)/28.0,0.2797,.001); + Assert.assertEquals(bc.getVertexRankScore(2)/28.0,0.0892,.001); + Assert.assertEquals(bc.getVertexRankScore(3)/28.0,0.0892,.001); + Assert.assertEquals(bc.getVertexRankScore(4)/28.0,0.2797,.001); + Assert.assertEquals(bc.getVertexRankScore(5)/28.0,0.2142,.001); + Assert.assertEquals(bc.getVertexRankScore(6)/28.0,0.1666,.001); + Assert.assertEquals(bc.getVertexRankScore(7)/28.0,0.1428,.001); + Assert.assertEquals(bc.getVertexRankScore(8)/28.0,0.1666,.001); + + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(0,1)), + 10.66666,.001); + + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(0,1)),10.66666,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(0,6)),9.33333,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(1,2)),6.5,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(1,3)),6.5,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(2,4)),6.5,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(3,4)),6.5,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(4,5)),10.66666,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(5,8)),9.33333,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(6,7)),8.0,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(7,8)),8.0,.001); + } + + public void testRankerDirected() { + DirectedGraph graph = new DirectedSparseGraph(); + for(int i=0; i<5; i++) { + graph.addVertex(i); + } + + int edge=0; + graph.addEdge(edge++, 0,1); + graph.addEdge(edge++, 1,2); + graph.addEdge(edge++, 3,1); + graph.addEdge(edge++, 4,2); + + BetweennessCentrality bc = + new BetweennessCentrality(graph); + bc.setRemoveRankScoresOnFinalize(false); + bc.evaluate(); + + Assert.assertEquals(bc.getVertexRankScore(0),0,.001); + Assert.assertEquals(bc.getVertexRankScore(1),2,.001); + Assert.assertEquals(bc.getVertexRankScore(2),0,.001); + Assert.assertEquals(bc.getVertexRankScore(3),0,.001); + Assert.assertEquals(bc.getVertexRankScore(4),0,.001); + + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(0,1)),2,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(1,2)),3,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(3,1)),2,.001); + Assert.assertEquals(bc.getEdgeRankScore(graph.findEdge(4,2)),1,.001); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestKStepMarkov.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestKStepMarkov.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestKStepMarkov.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestKStepMarkov.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,86 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + + +/** + * @author Scott White + * @author Tom Nelson - adapted to jung2 + */ +public class TestKStepMarkov extends TestCase { + public final static String EDGE_WEIGHT = "edu.uci.ics.jung.edge_weight"; + DirectedGraph mGraph; + double[][] mTransitionMatrix; + Map edgeWeights = new HashMap(); + + public static Test suite() { + return new TestSuite(TestKStepMarkov.class); + } + + @Override + protected void setUp() + { + mGraph = new DirectedSparseMultigraph(); + mTransitionMatrix = new double[][] + {{0.0, 0.5, 0.5}, + {1.0/3.0, 0.0, 2.0/3.0}, + {1.0/3.0, 2.0/3.0, 0.0}}; + + for (int i = 0; i < mTransitionMatrix.length; i++) + mGraph.addVertex(i); + + for (int i = 0; i < mTransitionMatrix.length; i++) { + for (int j = 0; j < mTransitionMatrix[i].length; j++) + { + if (mTransitionMatrix[i][j] > 0) + { + int edge = i*mTransitionMatrix.length+j; + mGraph.addEdge(edge, i, j); + edgeWeights.put(edge, mTransitionMatrix[i][j]); + } + } + } + } + + public void testRanker() { + + Set priors = new HashSet(); + priors.add(1); + priors.add(2); + KStepMarkov ranker = new KStepMarkov(mGraph,priors,2,edgeWeights); +// ranker.evaluate(); +// System.out.println(ranker.getIterations()); + + for (int i = 0; i < 10; i++) + { +// System.out.println(ranker.getIterations()); +// for (Number n : mGraph.getVertices()) +// System.out.println(n + ": " + ranker.getVertexRankScore(n)); + + ranker.step(); + } + + + List> rankings = ranker.getRankings(); +// System.out.println(rankings); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestWeightedNIPaths.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestWeightedNIPaths.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestWeightedNIPaths.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/importance/TestWeightedNIPaths.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,85 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.importance; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + +/** + * @author Scott White, adapted to jung2 by Tom Nelson + */ +public class TestWeightedNIPaths extends TestCase { + + Supplier vertexFactory; + Supplier edgeFactory; + + public static Test suite() { + return new TestSuite(TestWeightedNIPaths.class); + } + + @Override + protected void setUp() { + vertexFactory = new Supplier() { + char a = 'A'; + public String get() { + return Character.toString(a++); + }}; + edgeFactory = new Supplier() { + int count; + public Number get() { + return count++; + }}; + } + + public void testRanker() { + + DirectedGraph graph = new DirectedSparseMultigraph(); + for(int i=0; i<5; i++) { + graph.addVertex(vertexFactory.get()); + } + + graph.addEdge(edgeFactory.get(), "A", "B"); + graph.addEdge(edgeFactory.get(), "A", "C"); + graph.addEdge(edgeFactory.get(), "A", "D"); + graph.addEdge(edgeFactory.get(), "B", "A"); + graph.addEdge(edgeFactory.get(), "B", "E"); + graph.addEdge(edgeFactory.get(), "B", "D"); + graph.addEdge(edgeFactory.get(), "C", "A"); + graph.addEdge(edgeFactory.get(), "C", "E"); + graph.addEdge(edgeFactory.get(), "C", "D"); + graph.addEdge(edgeFactory.get(), "D", "A"); + graph.addEdge(edgeFactory.get(), "D", "B"); + graph.addEdge(edgeFactory.get(), "D", "C"); + graph.addEdge(edgeFactory.get(), "D", "E"); + + Set priors = new HashSet(); + priors.add("A"); + + WeightedNIPaths ranker = + new WeightedNIPaths(graph, vertexFactory, edgeFactory, 2.0,3,priors); + ranker.evaluate(); + + Assert.assertEquals(ranker.getRankings().get(0).rankScore,0.277787,.0001); + Assert.assertEquals(ranker.getRankings().get(1).rankScore,0.222222,.0001); + Assert.assertEquals(ranker.getRankings().get(2).rankScore,0.166676,.0001); + Assert.assertEquals(ranker.getRankings().get(3).rankScore,0.166676,.0001); + Assert.assertEquals(ranker.getRankings().get(4).rankScore,0.166676,.0001); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayout2Test.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayout2Test.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayout2Test.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayout2Test.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.algorithms.layout.util.VisRunner; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; + +public class FRLayout2Test extends TestCase { + + protected Set seedVertices = new HashSet(); + + public void testFRLayout() { + + Graph graph = TestGraphs.getOneComponentGraph(); + + Layout layout = new FRLayout2(graph); + layout.setSize(new Dimension(600,600)); + if(layout instanceof IterativeContext) { + layout.initialize(); + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.prerelax(); + relaxer.relax(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayoutTest.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayoutTest.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayoutTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/layout/FRLayoutTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,31 @@ +package edu.uci.ics.jung.algorithms.layout; + +import java.awt.Dimension; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.algorithms.layout.util.VisRunner; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; + +public class FRLayoutTest extends TestCase { + + protected Set seedVertices = new HashSet(); + + public void testFRLayout() { + + Graph graph = TestGraphs.getOneComponentGraph(); + + Layout layout = new FRLayout(graph); + layout.setSize(new Dimension(600,600)); + if(layout instanceof IterativeContext) { + layout.initialize(); + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.prerelax(); + relaxer.relax(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/metrics/TestTriad.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/metrics/TestTriad.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/metrics/TestTriad.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/metrics/TestTriad.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,166 @@ +package edu.uci.ics.jung.algorithms.metrics; + +import junit.framework.TestCase; +import edu.uci.ics.jung.algorithms.metrics.TriadicCensus; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + +public class TestTriad extends TestCase { + + public void testConfigurationFromPaper() { + DirectedGraph g = new DirectedSparseMultigraph(); + char u = 'u'; + g.addVertex(u); + char v = 'v'; + g.addVertex(v); + char w = 'w'; + g.addVertex(w); + g.addEdge(0, w, u); + g.addEdge(1, u, v); + g.addEdge(2, v, u); + + assertEquals(35, TriadicCensus.triCode(g, u, v, w)); + assertEquals(7, TriadicCensus.triType(35)); + assertEquals("111D", TriadicCensus.TRIAD_NAMES[7]); + + assertEquals(7, TriadicCensus.triType(TriadicCensus.triCode(g, u, w, v))); + assertEquals(7, TriadicCensus.triType(TriadicCensus.triCode(g, v, u, w))); + + long[] counts = TriadicCensus.getCounts(g); + + for (int i = 1; i <= 16; i++) { + if (i == 7) { + assertEquals(1, counts[i]); + } else { + assertEquals(0, counts[i]); + } + } + } + + public void testFourVertexGraph() { + // we'll set up a graph of + // t->u + // u->v + // and that's it. + // total count: + // 2: 1(t, u, w)(u, v, w) + // 6: 1(t, u, v) + // 1: 1(u, v, w) + DirectedGraph g = new DirectedSparseMultigraph(); + char u = 'u'; + g.addVertex(u); + char v = 'v'; + g.addVertex(v); + char w = 'w'; + g.addVertex(w); + char t = 't'; + g.addVertex(t); + + g.addEdge(0, t, u ); + g.addEdge(1, u, v ); + + long[] counts = TriadicCensus.getCounts(g); + for (int i = 1; i <= 16; i++) { + if( i == 2 ) { + assertEquals("On " + i, 2, counts[i]); + } else if (i == 6 || i == 1 ) { + assertEquals("On " + i, 1, counts[i]); + } else { + assertEquals(0, counts[i]); + } + } + + // now let's tweak to + // t->u, u->v, v->t + // w->u, v->w + g.addEdge(2, v, t ); + g.addEdge(3, w, u ); + g.addEdge(4, v, w ); + + // that's two 030Cs. it's a 021D (v-t, v-w) and an 021U (t-u, w-u) + counts = TriadicCensus.getCounts(g); + + for (int i = 1; i <= 16; i++) { + if( i == 10 /* 030C */ ) { + assertEquals("On " + i, 2, counts[i]); + } else if (i == 4 || i == 5 ) { + assertEquals("On " + i, 1, counts[i]); + } else { + assertEquals("On " + i , 0, counts[i]); + } + } + } + + public void testThreeDotsThreeDashes() { + DirectedGraph g = new DirectedSparseMultigraph(); + char u = 'u'; + g.addVertex(u); + char v = 'v'; + g.addVertex(v); + char w = 'w'; + g.addVertex(w); + + long[] counts = TriadicCensus.getCounts(g); + + for (int i = 1; i <= 16; i++) { + if (i == 1) { + assertEquals(1, counts[i]); + } else { + assertEquals(0, counts[i]); + } + } + + g.addEdge(0, v, u); + g.addEdge(1, u, v); + g.addEdge(2, v, w); + g.addEdge(3, w, v); + g.addEdge(4, u, w); + g.addEdge(5, w, u); + + counts = TriadicCensus.getCounts(g); + + for (int i = 1; i <= 16; i++) { + if (i == 16) { + assertEquals(1, counts[i]); + } else { + assertEquals("Count on " + i + " failed", 0, counts[i]); + } + } + } + + /** **************Boring accounting for zero graphs*********** */ + public void testNull() { + DirectedGraph g = new DirectedSparseMultigraph(); + long[] counts = TriadicCensus.getCounts(g); + + // t looks like a hashtable for the twelve keys + for (int i = 1; i < TriadicCensus.MAX_TRIADS; i++) { + assertEquals("Empty Graph doesn't have count 0", 0, counts[i]); + } + } + + public void testOneVertex() { + DirectedGraph g = new DirectedSparseMultigraph(); + g.addVertex('u'); + long[] counts = TriadicCensus.getCounts(g); + + // t looks like a hashtable for the twelve keys + for (int i = 1; i < TriadicCensus.MAX_TRIADS; i++) { + assertEquals("One vertex Graph doesn't have count 0", 0, counts[i]); + } + } + + public void testTwoVertices() { + DirectedGraph g = new DirectedSparseMultigraph(); + char v1, v2; + g.addVertex(v1 = 'u'); + g.addVertex(v2 = 'v'); + g.addEdge(0, v1, v2); + long[] counts = TriadicCensus.getCounts(g); + + // t looks like a hashtable for the twelve keys + for (int i = 1; i < TriadicCensus.MAX_TRIADS; i++) { + assertEquals("Two vertex Graph doesn't have count 0", 0, counts[i]); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestBetweennessCentrality.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestBetweennessCentrality.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestBetweennessCentrality.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestBetweennessCentrality.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Sep 17, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import junit.framework.TestCase; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Graph; + +/** + * + */ +public class TestBetweennessCentrality extends TestCase +{ +// public void testUndirected() { +// UndirectedGraph graph = +// new UndirectedSparseGraph(); +// for(int i=0; i<9; i++) { +// graph.addVertex(i); +// } +// +// int edge = 0; +// graph.addEdge(edge++, 0,1); +// graph.addEdge(edge++, 0,6); +// graph.addEdge(edge++, 1,2); +// graph.addEdge(edge++, 1,3); +// graph.addEdge(edge++, 2,4); +// graph.addEdge(edge++, 3,4); +// graph.addEdge(edge++, 4,5); +// graph.addEdge(edge++, 5,8); +// graph.addEdge(edge++, 7,8); +// graph.addEdge(edge++, 6,7); +// +// BetweennessCentrality bc = +// new BetweennessCentrality(graph); +// +//// System.out.println("scoring"); +//// for (int i = 0; i < graph.getVertexCount(); i++) +//// System.out.println(String.format("%d: %f", i, bc.getVertexScore(i))); +// +// Assert.assertEquals(bc.getVertexScore(0),6.000,.001); +// Assert.assertEquals(bc.getVertexScore(1),7.833,.001); +// Assert.assertEquals(bc.getVertexScore(2),2.500,.001); +// Assert.assertEquals(bc.getVertexScore(3),2.500,.001); +// Assert.assertEquals(bc.getVertexScore(4),7.833,.001); +// Assert.assertEquals(bc.getVertexScore(5),6.000,.001); +// Assert.assertEquals(bc.getVertexScore(6),4.666,.001); +// Assert.assertEquals(bc.getVertexScore(7),4.000,.001); +// Assert.assertEquals(bc.getVertexScore(8),4.666,.001); +// +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(0,1)),10.666,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(0,6)),9.333,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(1,2)),6.500,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(1,3)),6.500,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(2,4)),6.500,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(3,4)),6.500,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(4,5)),10.666,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(5,8)),9.333,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(6,7)),8.000,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(7,8)),8.000,.001); +// } +// +// public void testDirected() +// { +// DirectedGraph graph = new DirectedSparseGraph(); +// for(int i=0; i<5; i++) +// graph.addVertex(i); +// +// int edge=0; +// graph.addEdge(edge++, 0,1); +// graph.addEdge(edge++, 1,2); +// graph.addEdge(edge++, 3,1); +// graph.addEdge(edge++, 4,2); +// +// BetweennessCentrality bc = +// new BetweennessCentrality(graph); +// +// Assert.assertEquals(bc.getVertexScore(0),0,.001); +// Assert.assertEquals(bc.getVertexScore(1),2,.001); +// Assert.assertEquals(bc.getVertexScore(2),0,.001); +// Assert.assertEquals(bc.getVertexScore(3),0,.001); +// Assert.assertEquals(bc.getVertexScore(4),0,.001); +// +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(0,1)),2,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(1,2)),3,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(3,1)),2,.001); +// Assert.assertEquals(bc.getEdgeScore(graph.findEdge(4,2)),1,.001); +// } + + public void testWeighted() + { + Graph graph = new DirectedSparseGraph(); + + for(int i=0; i<5; i++) + graph.addVertex(i); + + char edge='a'; + graph.addEdge(edge++, 0,1); + graph.addEdge(edge++, 0,2); + graph.addEdge(edge++, 2,3); + graph.addEdge(edge++, 3,1); + graph.addEdge(edge++, 1,4); + + final int weights[] = {1, 1, 1, 1, 1}; + + Function edge_weights = new Function() + { + public Integer apply(Character arg0) { return weights[arg0 - 'a']; } + }; + + BetweennessCentrality bc = + new BetweennessCentrality(graph, edge_weights); + +// System.out.println("scoring"); +// System.out.println("(weighted)"); +// System.out.println("vertices:"); +// for (int i = 0; i < graph.getVertexCount(); i++) +// System.out.println(String.format("%d: %f", i, bc.getVertexScore(i))); +// System.out.println("edges:"); +// for (int i = 0; i < graph.getEdgeCount(); i++) +// { +// char e = (char)(i + 'a'); +// System.out.println(String.format("%c: (weight: %d), %f", e, +// edge_weights.apply(e), bc.getEdgeScore(e))); +// } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITS.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITS.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITS.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITS.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,119 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.scoring; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + + +/** + * @author Scott White + * @author Tom Nelson - adapted to jung2 + */ +public class TestHITS extends TestCase { + + DirectedGraph graph; + + public static Test suite() { + return new TestSuite(TestHITS.class); + } + + @Override + protected void setUp() { + graph = new DirectedSparseMultigraph(); + for(int i=0; i<5; i++) { + graph.addVertex(i); + } + + int j=0; + graph.addEdge(j++, 0, 1); + graph.addEdge(j++, 1, 2); + graph.addEdge(j++, 2, 3); + graph.addEdge(j++, 3, 0); + graph.addEdge(j++, 2, 1); + } + + public void testRanker() { + + HITS ranker = new HITS(graph); + for (int i = 0; i < 10; i++) + { + ranker.step(); +// // check hub scores in terms of previous authority scores +// Assert.assertEquals(t.transform(0).hub, +// 0.5*ranker.getAuthScore(1) + 0.2*ranker.getAuthScore(4)); +// Assert.assertEquals(t.transform(1).hub, +// ranker.getAuthScore(2) + 0.2*ranker.getAuthScore(4)); +// Assert.assertEquals(t.transform(2).hub, +// 0.5*ranker.getAuthScore(1) + ranker.getAuthScore(3) + 0.2*ranker.getAuthScore(4)); +// Assert.assertEquals(t.transform(3).hub, +// ranker.getAuthScore(0) + 0.2*ranker.getAuthScore(4)); +// Assert.assertEquals(t.transform(4).hub, +// 0.2*ranker.getAuthScore(4)); +// +// // check authority scores in terms of previous hub scores +// Assert.assertEquals(t.transform(0).authority, +// ranker.getVertexScore(3) + 0.2*ranker.getVertexScore(4)); +// Assert.assertEquals(t.transform(1).authority, +// ranker.getVertexScore(0) + 0.5 * ranker.getVertexScore(2) + 0.2*ranker.getVertexScore(4)); +// Assert.assertEquals(t.transform(2).authority, +// ranker.getVertexScore(1) + 0.2*ranker.getVertexScore(4)); +// Assert.assertEquals(t.transform(3).authority, +// 0.5*ranker.getVertexScore(2) + 0.2*ranker.getVertexScore(4)); +// Assert.assertEquals(t.transform(4).authority, +// 0.2*ranker.getVertexScore(4)); +// + // verify that sums of each scores are 1.0 + double auth_sum = 0; + double hub_sum = 0; + for (int j = 0; j < 5; j++) + { +// auth_sum += ranker.getAuthScore(j); +// hub_sum += ranker.getVertexScore(j); +// auth_sum += (ranker.getAuthScore(j) * ranker.getAuthScore(j)); +// hub_sum += (ranker.getVertexScore(j) * ranker.getVertexScore(j)); + HITS.Scores score = ranker.getVertexScore(j); + auth_sum += score.authority * score.authority; + hub_sum += score.hub * score.hub; + } + Assert.assertEquals(auth_sum, 1.0, .0001); + Assert.assertEquals(hub_sum, 1.0, 0.0001); + } + + ranker.evaluate(); + + Assert.assertEquals(ranker.getVertexScore(0).authority, 0, .0001); + Assert.assertEquals(ranker.getVertexScore(1).authority, 0.8507, .001); + Assert.assertEquals(ranker.getVertexScore(2).authority, 0.0, .0001); + Assert.assertEquals(ranker.getVertexScore(3).authority, 0.5257, .001); + + Assert.assertEquals(ranker.getVertexScore(0).hub, 0.5257, .001); + Assert.assertEquals(ranker.getVertexScore(1).hub, 0.0, .0001); + Assert.assertEquals(ranker.getVertexScore(2).hub, 0.8507, .0001); + Assert.assertEquals(ranker.getVertexScore(3).hub, 0.0, .0001); + + // the values below assume scores sum to 1 + // (rather than that sum of squares of scores sum to 1) +// Assert.assertEquals(ranker.getVertexScore(0).authority, 0, .0001); +// Assert.assertEquals(ranker.getVertexScore(1).authority, 0.618, .001); +// Assert.assertEquals(ranker.getVertexScore(2).authority, 0.0, .0001); +// Assert.assertEquals(ranker.getVertexScore(3).authority, 0.3819, .001); +// +// Assert.assertEquals(ranker.getVertexScore(0).hub, 0.38196, .001); +// Assert.assertEquals(ranker.getVertexScore(1).hub, 0.0, .0001); +// Assert.assertEquals(ranker.getVertexScore(2).hub, 0.618, .0001); +// Assert.assertEquals(ranker.getVertexScore(3).hub, 0.0, .0001); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITSWithPriors.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITSWithPriors.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITSWithPriors.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestHITSWithPriors.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,77 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + + +/** + * Tests HITSWithPriors. + */ +public class TestHITSWithPriors extends TestCase { + + DirectedGraph graph; + Set roots; + + public static Test suite() { + return new TestSuite(TestHITSWithPriors.class); + } + + @Override + protected void setUp() { + graph = new DirectedSparseMultigraph(); + for(int i=0; i<4; i++) { + graph.addVertex(i); + } + int j=0; + graph.addEdge(j++, 0, 1); + graph.addEdge(j++, 1, 2); + graph.addEdge(j++, 2, 3); + graph.addEdge(j++, 3, 0); + graph.addEdge(j++, 2, 1); + + roots = new HashSet(); + roots.add(2); + } + + public void testRankings() { + + HITSWithPriors ranker = + new HITSWithPriors(graph, ScoringUtils.getHITSUniformRootPrior(roots), 0.3); + ranker.evaluate(); + + double[] expected_auth = {0.0, 0.765, 0.365, 0.530}; + double[] expected_hub = {0.398, 0.190, 0.897, 0.0}; + + double hub_sum = 0; + double auth_sum = 0; + for (Number n : graph.getVertices()) + { + int i = n.intValue(); + double auth = ranker.getVertexScore(i).authority; + double hub = ranker.getVertexScore(i).hub; + Assert.assertEquals(auth, expected_auth[i], 0.001); + Assert.assertEquals(hub, expected_hub[i], 0.001); + hub_sum += hub * hub; + auth_sum += auth * auth; + } + Assert.assertEquals(1.0, hub_sum, 0.001); + Assert.assertEquals(1.0, auth_sum, 0.001); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestKStepMarkov.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestKStepMarkov.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestKStepMarkov.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestKStepMarkov.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,70 @@ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + +public class TestKStepMarkov extends TestCase +{ + DirectedGraph mGraph; + double[][] mTransitionMatrix; + Map edgeWeights = new HashMap(); + + @Override + protected void setUp() + { + mGraph = new DirectedSparseMultigraph(); + mTransitionMatrix = new double[][] + {{0.0, 0.5, 0.5}, + {1.0/3.0, 0.0, 2.0/3.0}, + {1.0/3.0, 2.0/3.0, 0.0}}; + + for (int i = 0; i < mTransitionMatrix.length; i++) + mGraph.addVertex(i); + + for (int i = 0; i < mTransitionMatrix.length; i++) { + for (int j = 0; j < mTransitionMatrix[i].length; j++) + { + if (mTransitionMatrix[i][j] > 0) + { + int edge = i*mTransitionMatrix.length+j; + mGraph.addEdge(edge, i, j); + edgeWeights.put(edge, mTransitionMatrix[i][j]); + } + } + } + } + + public void testRanker() { + + Set priors = new HashSet(); + priors.add(1); + priors.add(2); + KStepMarkov ranker = + new KStepMarkov(mGraph, Functions.forMap(edgeWeights), + ScoringUtils.getUniformRootPrior(priors),2); +// ranker.evaluate(); +// System.out.println(ranker.getIterations()); + + for (int i = 0; i < 10; i++) + { +// System.out.println(ranker.getIterations()); +// for (Number n : mGraph.getVertices()) +// System.out.println(n + ": " + ranker.getVertexScore(n)); + ranker.step(); + } +// List> rankings = ranker.getRankings(); +// System.out.println("New version:"); +// System.out.println(rankings); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRank.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRank.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRank.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRank.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; + +/** + * @author Joshua O'Madadhain + */ +public class TestPageRank extends TestCase { + + private Map edgeWeights; + private DirectedGraph graph; + private Supplier edgeFactory; + + public static Test suite() { + return new TestSuite(TestPageRank.class); + } + + @Override + protected void setUp() { + edgeWeights = new HashMap(); + edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + } + + private void addEdge(Graph G, Integer v1, Integer v2, double weight) { + Integer edge = edgeFactory.get(); + graph.addEdge(edge, v1, v2); + edgeWeights.put(edge, weight); + } + + public void testRanker() { + graph = new DirectedSparseMultigraph(); + for(int i=0; i<4; i++) { + graph.addVertex(i); + } + addEdge(graph,0,1,1.0); + addEdge(graph,1,2,1.0); + addEdge(graph,2,3,0.5); + addEdge(graph,3,1,1.0); + addEdge(graph,2,1,0.5); + + PageRankWithPriors pr = new PageRank(graph, Functions.forMap(edgeWeights), 0); + pr.evaluate(); + + Assert.assertEquals(pr.getVertexScore(0), 0.0, pr.getTolerance()); + Assert.assertEquals(pr.getVertexScore(1), 0.4, pr.getTolerance()); + Assert.assertEquals(pr.getVertexScore(2), 0.4, pr.getTolerance()); + Assert.assertEquals(pr.getVertexScore(3), 0.2, pr.getTolerance()); + +// Assert.assertTrue(NumericalPrecision.equal(((Ranking)ranker.getRankings().get(0)).rankScore,0.4,.001)); +// Assert.assertTrue(NumericalPrecision.equal(((Ranking)ranker.getRankings().get(1)).rankScore,0.4,.001)); +// Assert.assertTrue(NumericalPrecision.equal(((Ranking)ranker.getRankings().get(2)).rankScore,0.2,.001)); +// Assert.assertTrue(NumericalPrecision.equal(((Ranking)ranker.getRankings().get(3)).rankScore,0,.001)); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRankWithPriors.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRankWithPriors.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRankWithPriors.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestPageRankWithPriors.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,91 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.scoring.util.ScoringUtils; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; + + +/** + * @author Scott White + */ +public class TestPageRankWithPriors extends TestCase { + +// private Map edgeWeights; + private DirectedGraph graph; + private Supplier edgeFactory; + + public static Test suite() { + return new TestSuite(TestPageRankWithPriors.class); + } + + @Override + protected void setUp() { +// edgeWeights = new HashMap(); + edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + } + + private void addEdge(Graph G, Integer v1, Integer v2) + { + Integer edge = edgeFactory.get(); + graph.addEdge(edge, v1, v2); +// edgeWeights.put(edge, weight); + } + + public void testGraphScoring() { + graph = new DirectedSparseMultigraph(); + + double[] expected_score = new double[]{0.1157, 0.2463, 0.4724, 0.1653}; + + for(int i=0; i<4; i++) { + graph.addVertex(i); + } + addEdge(graph,0,1); + addEdge(graph,1,2); + addEdge(graph,2,3); + addEdge(graph,3,0); + addEdge(graph,2,1); + + Set priors = new HashSet(); + priors.add(2); + + PageRankWithPriors pr = + new PageRankWithPriors(graph, ScoringUtils.getUniformRootPrior(priors), 0.3); + pr.evaluate(); + + double score_sum = 0; + for (int i = 0; i < graph.getVertexCount(); i++) + { + double score = pr.getVertexScore(i); + Assert.assertEquals(expected_score[i], score, pr.getTolerance()); + score_sum += score; + } + Assert.assertEquals(1.0, score_sum, pr.getTolerance() * graph.getVertexCount()); + } + + public void testHypergraphScoring() { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestVoltageScore.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestVoltageScore.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestVoltageScore.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/scoring/TestVoltageScore.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jul 14, 2008 + * + */ +package edu.uci.ics.jung.algorithms.scoring; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +/** + * @author jrtom + * + */ +public class TestVoltageScore extends TestCase +{ + protected Graph g; + + @Override + public void setUp() { + g = new UndirectedSparseMultigraph(); + for (int i = 0; i < 7; i++) { + g.addVertex(i); + } + + int j = 0; + g.addEdge(j++,0,1); + g.addEdge(j++,0,2); + g.addEdge(j++,1,3); + g.addEdge(j++,2,3); + g.addEdge(j++,3,4); + g.addEdge(j++,3,5); + g.addEdge(j++,4,6); + g.addEdge(j++,5,6); + } + + public final void testCalculateVoltagesSourceTarget() { + VoltageScorer vr = new VoltageScorer(g, Functions.constant(1), 0, 6); + double[] voltages = {1.0, 0.75, 0.75, 0.5, 0.25, 0.25, 0}; + + vr.evaluate(); + for (int i = 0; i < 7; i++) { + assertEquals(vr.getVertexScore(i), voltages[i], 0.01); + } + } + + public final void testCalculateVoltagesSourcesTargets() + { + Map sources = new HashMap(); + sources.put(0, new Double(1.0)); + sources.put(1, new Double(0.5)); + Set sinks = new HashSet(); + sinks.add(6); + sinks.add(5); + VoltageScorer vr = + new VoltageScorer(g, Functions.constant(1), sources, sinks); + double[] voltages = {1.0, 0.5, 0.66, 0.33, 0.16, 0, 0}; + + vr.evaluate(); + for (int i = 0; i < 7; i++) { + assertEquals(vr.getVertexScore(i), voltages[i], 0.01); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestBFSDistanceLabeler.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestBFSDistanceLabeler.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestBFSDistanceLabeler.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestBFSDistanceLabeler.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,67 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.algorithms.shortestpath; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; +import edu.uci.ics.jung.algorithms.shortestpath.BFSDistanceLabeler; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +/** + * @author Scott White, adapted to jung2 by Tom Nelson + */ +public class TestBFSDistanceLabeler extends TestCase { + public static Test suite() { + return new TestSuite(TestBFSDistanceLabeler.class); + } + + @Override + protected void setUp() { + + } + + public void test() { + Graph graph = new UndirectedSparseMultigraph(); + for(int i=0; i<6; i++) { + graph.addVertex(i); + } + int j = 0; + graph.addEdge(j++,0,1); + graph.addEdge(j++,0,5); + graph.addEdge(j++,0,3); + graph.addEdge(j++,0,4); + graph.addEdge(j++,1,5); + graph.addEdge(j++,3,4); + graph.addEdge(j++,3,2); + graph.addEdge(j++,5,2); + Number root = 0; + + BFSDistanceLabeler labeler = new BFSDistanceLabeler(); + labeler.labelDistances(graph,root); + + Assert.assertEquals(labeler.getPredecessors(root).size(),0); + Assert.assertEquals(labeler.getPredecessors(1).size(),1); + Assert.assertEquals(labeler.getPredecessors(2).size(),2); + Assert.assertEquals(labeler.getPredecessors(3).size(),1); + Assert.assertEquals(labeler.getPredecessors(4).size(),1); + Assert.assertEquals(labeler.getPredecessors(5).size(),1); + + Assert.assertEquals(labeler.getDistance(graph,0),0); + Assert.assertEquals(labeler.getDistance(graph,1),1); + Assert.assertEquals(labeler.getDistance(graph,2),2); + Assert.assertEquals(labeler.getDistance(graph,3),1); + Assert.assertEquals(labeler.getDistance(graph,4),1); + Assert.assertEquals(labeler.getDistance(graph,5),1); + + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestPrimMinimumSpanningTree.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestPrimMinimumSpanningTree.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestPrimMinimumSpanningTree.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestPrimMinimumSpanningTree.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,62 @@ +package edu.uci.ics.jung.algorithms.shortestpath; + +import junit.framework.TestCase; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +public class TestPrimMinimumSpanningTree extends TestCase { + + public void testSimpleTree() { + Tree tree = new DelegateTree(); + tree.addVertex("A"); + tree.addEdge(0,"A","B0"); + tree.addEdge(1,"A","B1"); + +// System.err.println("tree = "+tree); + PrimMinimumSpanningTree pmst = + new PrimMinimumSpanningTree(DelegateTree.getFactory()); + +// Graph mst = + pmst.apply(tree); +// System.err.println("mst = "+mst); + +// assertEquals(tree.getVertices(), mst.getVertices()); +// assertEquals(tree.getEdges(), mst.getEdges()); + + } + + public void testDAG() { + DirectedGraph graph = new DirectedSparseMultigraph(); + graph.addVertex("B0"); + graph.addEdge(0, "A", "B0"); + graph.addEdge(1, "A", "B1"); +// System.err.println("graph = "+graph); + PrimMinimumSpanningTree pmst = + new PrimMinimumSpanningTree(DelegateTree.getFactory()); + +// Graph mst = + pmst.apply(graph); +// System.err.println("mst = "+mst); + + } + + public void testUAG() { + UndirectedGraph graph = new UndirectedSparseMultigraph(); + graph.addVertex("B0"); + graph.addEdge(0, "A", "B0"); + graph.addEdge(1, "A", "B1"); +// System.err.println("graph = "+graph); + PrimMinimumSpanningTree pmst = + new PrimMinimumSpanningTree(DelegateTree.getFactory()); + +// Graph mst = + pmst.apply(graph); +// System.err.println("mst = "+mst); + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestShortestPath.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestShortestPath.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestShortestPath.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestShortestPath.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,528 @@ +/* + * Created on Aug 22, 2003 + * + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.common.collect.BiMap; + +import edu.uci.ics.jung.algorithms.util.Indexer; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + + +/** + * @author Joshua O'Madadhain + */ +public class TestShortestPath extends TestCase +{ + private DirectedGraph dg; + private UndirectedGraph ug; + // graph based on Weiss, _Data Structures and Algorithm Analysis_, + // 1992, p. 292 + private static int[][] edges = + {{1,2,2}, {1,4,1}, // 0, 1 + {2,4,3}, {2,5,10}, // 2, 3 + {3,1,4}, {3,6,5}, // 4, 5 + {4,3,2}, {4,5,2}, {4,6,8}, {4,7,4}, // 6,7,8,9 + {5,7,6}, // 10 + {7,6,1}, // 11 + {8,9,4}, // (12) these three edges define a second connected component + {9,10,1}, // 13 + {10,8,2}}; // 14 + + private static Integer[][] ug_incomingEdges = + { + {null, new Integer(0), new Integer(6), new Integer(1), new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {new Integer(0), null, new Integer(6), new Integer(2), new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {new Integer(1), new Integer(2), null, new Integer(6), new Integer(7), new Integer(5), new Integer(9), null, null, null}, + {new Integer(1), new Integer(2), new Integer(6), null, new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {new Integer(1), new Integer(2), new Integer(6), new Integer(7), null, new Integer(11), new Integer(10), null, null, null}, + {new Integer(1), new Integer(2), new Integer(5), new Integer(9), new Integer(10), null, new Integer(11), null, null, null}, + {new Integer(1), new Integer(2), new Integer(5), new Integer(9), new Integer(10), new Integer(11), null, null, null, null}, + {null, null, null, null, null, null, null, null, new Integer(13), new Integer(14)}, + {null, null, null, null, null, null, null, new Integer(14), null, new Integer(13)}, + {null, null, null, null, null, null, null, new Integer(14), new Integer(13), null}, + }; + + private static Integer[][] dg_incomingEdges = + { + {null, new Integer(0), new Integer(6), new Integer(1), new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {new Integer(4), null, new Integer(6), new Integer(2), new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {new Integer(4), new Integer(0), null, new Integer(1), new Integer(7), new Integer(5), new Integer(9), null, null, null}, + {new Integer(4), new Integer(0), new Integer(6), null, new Integer(7), new Integer(11), new Integer(9), null, null, null}, + {null, null, null, null, null, new Integer(11), new Integer(10), null, null, null}, + {null, null, null, null, null, null, null, null, null, null}, + {null, null, null, null, null, new Integer(11), null, null, null, null}, + {null, null, null, null, null, null, null, null, new Integer(12), new Integer(13)}, + {null, null, null, null, null, null, null, new Integer(14), null, new Integer(13)}, + {null, null, null, null, null, null, null, new Integer(14), new Integer(12), null} + }; + + private static double[][] dg_distances = + { + {0, 2, 3, 1, 3, 6, 5, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {9, 0, 5, 3, 5, 8, 7, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {4, 6, 0, 5, 7, 5, 9, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {6, 8, 2, 0, 2, 5, 4, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 0, 7, 6, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 0, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 1, 0, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 0, 4, 5}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 3, 0, 1}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 2, 6, 0} + }; + + private static double[][] ug_distances = + { + {0, 2, 3, 1, 3, 6, 5, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {2, 0, 5, 3, 5, 8, 7, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {3, 5, 0, 2, 4, 5, 6, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {1, 3, 2, 0, 2, 5, 4, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {3, 5, 4, 2, 0, 7, 6, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {6, 8, 5, 5, 7, 0, 1, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {5, 7, 6, 4, 6, 1, 0, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 0, 3, 2}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 3, 0, 1}, + {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 2, 1, 0} + }; + + + private static Integer[][] shortestPaths1 = + { + null, + {new Integer(0)}, + {new Integer(1), new Integer(6)}, + {new Integer(1)}, + {new Integer(1), new Integer(7)}, + {new Integer(1), new Integer(9), new Integer(11)}, + {new Integer(1), new Integer(9)}, + null, + null, + null + }; + + private Map,Integer[]> edgeArrays; + + private Map edgeWeights; + + private Function nev; + + private Supplier vertexFactoryDG = + new Supplier() { + int count = 0; + public String get() { + return "V"+count++; + }}; + private Supplier vertexFactoryUG = + new Supplier() { + int count = 0; + public String get() { + return "U"+count++; + }}; + + BiMap did; + BiMap uid; + + @Override + protected void setUp() { + edgeWeights = new HashMap(); + nev = Functions.forMap(edgeWeights); + dg = new DirectedSparseMultigraph(); + for(int i=0; icreate(dg.getVertices(), 1); + Integer[] dg_array = new Integer[edges.length]; + addEdges(dg, did, dg_array); + + ug = new UndirectedSparseMultigraph(); + for(int i=0; icreate(ug.getVertices(),1); +// GraphUtils.addVertices(ug, ug_distances.length); +// Indexer.newIndexer(ug, 1); + Integer[] ug_array = new Integer[edges.length]; + addEdges(ug, uid, ug_array); + + edgeArrays = new HashMap,Integer[]>(); + edgeArrays.put(dg, dg_array); + edgeArrays.put(ug, ug_array); + } + + @Override + protected void tearDown() throws Exception { + } + + public void exceptionTest(Graph g, BiMap indexer, int index) + { + DijkstraShortestPath dsp = + new DijkstraShortestPath(g, nev); +// Indexer id = Indexer.getIndexer(g); + String start = indexer.inverse().get(index); + Integer e = null; + + String v = "NOT IN GRAPH"; + + try + { + dsp.getDistance(start, v); + fail("getDistance(): illegal destination vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getDistance(v, start); + fail("getDistance(): illegal source vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getDistanceMap(v, 1); + fail("getDistanceMap(): illegal source vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getDistanceMap(start, 0); + fail("getDistanceMap(): too few vertices requested"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getDistanceMap(start, g.getVertexCount()+1); + fail("getDistanceMap(): too many vertices requested"); + } + catch (IllegalArgumentException iae) {} + + try + { + dsp.getIncomingEdge(start, v); + fail("getIncomingEdge(): illegal destination vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getIncomingEdge(v, start); + fail("getIncomingEdge(): illegal source vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getIncomingEdgeMap(v, 1); + fail("getIncomingEdgeMap(): illegal source vertex"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getIncomingEdgeMap(start, 0); + fail("getIncomingEdgeMap(): too few vertices requested"); + } + catch (IllegalArgumentException iae) {} + try + { + dsp.getDistanceMap(start, g.getVertexCount()+1); + fail("getIncomingEdgeMap(): too many vertices requested"); + } + catch (IllegalArgumentException iae) {} + + try + { + // test negative edge weight exception + String v1 = indexer.inverse().get(1); + String v2 = indexer.inverse().get(7); + e = g.getEdgeCount()+1; + g.addEdge(e, v1, v2); + edgeWeights.put(e, -2); +// e.addUserDatum("weight", new Double(-2), UserData.REMOVE); + dsp.reset(); + dsp.getDistanceMap(start); +// for (Iterator it = g.getEdges().iterator(); it.hasNext(); ) +// { +// Edge edge = (Edge)it.next(); +// double weight = ((Number)edge.getUserDatum("weight")).doubleValue(); +// Pair p = edge.getEndpoints(); +// int i = id.getIndex((Vertex)p.getFirst()); +// int j = id.getIndex((Vertex)p.getSecond()); +// System.out.print("(" + i + "," + j + "): " + weight); +// if (weight < 0) +// System.out.print(" *******"); +// System.out.println(); +// } + fail("DijkstraShortestPath should not accept negative edge weights"); + } + catch (IllegalArgumentException iae) + { + g.removeEdge(e); + } + } + + public void testDijkstra() + { + setUp(); + exceptionTest(dg, did, 1); + + setUp(); + exceptionTest(ug, uid, 1); + + setUp(); + getPathTest(dg, did, 1); + + setUp(); + getPathTest(ug, uid, 1); + + for (int i = 1; i <= dg_distances.length; i++) + { + setUp(); + weightedTest(dg, did, i, true); + + setUp(); + weightedTest(dg, did, i, false); + } + + for (int i = 1; i <= ug_distances.length; i++) + { + setUp(); + weightedTest(ug, uid, i, true); + + setUp(); + weightedTest(ug, uid, i, false); + } + + } + + private void getPathTest(Graph g, BiMap indexer, int index) + { + DijkstraShortestPath dsp = + new DijkstraShortestPath(g, nev); +// Indexer id = Indexer.getIndexer(g); + String start = indexer.inverse().get(index); + Integer[] edge_array = edgeArrays.get(g); + Integer[] incomingEdges1 = null; + if (g instanceof DirectedGraph) + incomingEdges1 = dg_incomingEdges[index-1]; + if (g instanceof UndirectedGraph) + incomingEdges1 = ug_incomingEdges[index-1]; + assertEquals(incomingEdges1.length, g.getVertexCount()); + + // test getShortestPath(start, v) + dsp.reset(); + for (int i = 1; i <= incomingEdges1.length; i++) + { + List shortestPath = dsp.getPath(start, indexer.inverse().get(i)); + Integer[] indices = shortestPaths1[i-1]; + for (ListIterator iter = shortestPath.listIterator(); iter.hasNext(); ) + { + int j = iter.nextIndex(); + Integer e = iter.next(); + if (e != null) + assertEquals(edge_array[indices[j].intValue()], e); + else + assertNull(indices[j]); + } + } + } + + private void weightedTest(Graph g, BiMap indexer, int index, boolean cached) { +// Indexer id = Indexer.getIndexer(g); + String start = indexer.inverse().get(index); + double[] distances1 = null; + Integer[] incomingEdges1 = null; + if (g instanceof DirectedGraph) + { + distances1 = dg_distances[index-1]; + incomingEdges1 = dg_incomingEdges[index-1]; + } + if (g instanceof UndirectedGraph) + { + distances1 = ug_distances[index-1]; + incomingEdges1 = ug_incomingEdges[index-1]; + } + assertEquals(distances1.length, g.getVertexCount()); + assertEquals(incomingEdges1.length, g.getVertexCount()); + DijkstraShortestPath dsp = + new DijkstraShortestPath(g, nev, cached); + Integer[] edge_array = edgeArrays.get(g); + + // test getDistance(start, v) + for (int i = 1; i <= distances1.length; i++) { + String v = indexer.inverse().get(i); + Number n = dsp.getDistance(start, v); + double d = distances1[i-1]; + double dist; + if (n == null) + dist = Double.POSITIVE_INFINITY; + else + dist = n.doubleValue(); + + assertEquals(d, dist, .001); + } + + // test getIncomingEdge(start, v) + dsp.reset(); + for (int i = 1; i <= incomingEdges1.length; i++) + { + String v = indexer.inverse().get(i); + Integer e = dsp.getIncomingEdge(start, v); + if (e != null) + assertEquals(edge_array[incomingEdges1[i-1].intValue()], e); + else + assertNull(incomingEdges1[i-1]); + } + + // test getDistanceMap(v) + dsp.reset(); + Map distances = dsp.getDistanceMap(start); + assertTrue(distances.size() <= g.getVertexCount()); + double d_prev = 0; // smallest possible distance + Set reachable = new HashSet(); + for (Iterator d_iter = distances.keySet().iterator(); d_iter.hasNext(); ) + { + String cur = d_iter.next(); + double d_cur = ((Double)distances.get(cur)).doubleValue(); + assertTrue(d_cur >= d_prev); + + d_prev = d_cur; + int i = indexer.get(cur); + assertEquals(distances1[i-1], d_cur, .001); + reachable.add(cur); + } + // make sure that non-reachable vertices have no entries + for (Iterator v_iter = g.getVertices().iterator(); v_iter.hasNext(); ) + { + String v = v_iter.next(); + assertEquals(reachable.contains(v), distances.keySet().contains(v)); + } + + // test getIncomingEdgeMap(v) + dsp.reset(); + Map incomingEdgeMap = dsp.getIncomingEdgeMap(start); + assertTrue(incomingEdgeMap.size() <= g.getVertexCount()); + for (Iterator e_iter = incomingEdgeMap.keySet().iterator(); e_iter.hasNext(); ) + { + String v = e_iter.next(); + Integer e = incomingEdgeMap.get(v); + int i = indexer.get(v); +// if (e != null) +// { +// Pair endpoints = e.getEndpoints(); +// int j = id.getIndex((Vertex)endpoints.getFirst()); +// int k = id.getIndex((Vertex)endpoints.getSecond()); +// System.out.print(i + ": (" + j + "," + k + "); "); +// } +// else +// System.out.print(i + ": null; "); + if (e != null) + assertEquals(edge_array[incomingEdges1[i-1].intValue()], e); + else + assertNull(incomingEdges1[i-1]); + } + + // test getDistanceMap(v, k) + dsp.reset(); + for (int i = 1; i <= distances1.length; i++) + { + distances = dsp.getDistanceMap(start, i); + assertTrue(distances.size() <= i); + d_prev = 0; // smallest possible distance + + reachable.clear(); + for (Iterator d_iter = distances.keySet().iterator(); d_iter.hasNext(); ) + { + String cur = d_iter.next(); + double d_cur = ((Double)distances.get(cur)).doubleValue(); + assertTrue(d_cur >= d_prev); + + d_prev = d_cur; + int j = indexer.get(cur); + + assertEquals(distances1[j-1], d_cur, .001); + reachable.add(cur); + } + for (Iterator v_iter = g.getVertices().iterator(); v_iter.hasNext(); ) + { + String v = v_iter.next(); + assertEquals(reachable.contains(v), distances.keySet().contains(v)); + } + } + + // test getIncomingEdgeMap(v, k) + dsp.reset(); + for (int i = 1; i <= incomingEdges1.length; i++) + { + incomingEdgeMap = dsp.getIncomingEdgeMap(start, i); + assertTrue(incomingEdgeMap.size() <= i); + for (Iterator e_iter = incomingEdgeMap.keySet().iterator(); e_iter.hasNext(); ) + { + String v = e_iter.next(); + Integer e = incomingEdgeMap.get(v); + int j = indexer.get(v); + if (e != null) + assertEquals(edge_array[incomingEdges1[j-1].intValue()], e); + else + assertNull(incomingEdges1[j-1]); + } + } + } + + public void addEdges(Graph g, BiMap indexer, Integer[] edge_array) + { + +// Indexer id = Indexer.getIndexer(g); + for (int i = 0; i < edges.length; i++) + { + int[] edge = edges[i]; + Integer e = i; + g.addEdge(i, indexer.inverse().get(edge[0]), indexer.inverse().get(edge[1])); + edge_array[i] = e; + if (edge.length > 2) { + edgeWeights.put(e, edge[2]); +// e.addUserDatum("weight", edge[2]); + } + } + } + + +// private class UserDataEdgeWeight implements NumberEdgeValue +// { +// private Object ud_key; +// +// public UserDataEdgeWeight(Object key) +// { +// ud_key = key; +// } +// +// /** +// * @see edu.uci.ics.jung.utils.NumberEdgeValue#getNumber(edu.uci.ics.jung.graph.ArchetypeEdge) +// */ +// public Number getNumber(ArchetypeEdge e) +// { +// return (Number)e.getUserDatum(ud_key); +// } +// +// /** +// * @see edu.uci.ics.jung.utils.NumberEdgeValue#setNumber(edu.uci.ics.jung.graph.ArchetypeEdge, java.lang.Number) +// */ +// public void setNumber(ArchetypeEdge e, Number n) +// { +// throw new UnsupportedOperationException(); +// } +// } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestUnweightedShortestPath.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestUnweightedShortestPath.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestUnweightedShortestPath.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/shortestpath/TestUnweightedShortestPath.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Created on Aug 22, 2003 + * + */ +package edu.uci.ics.jung.algorithms.shortestpath; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; +import com.google.common.collect.BiMap; + +import edu.uci.ics.jung.algorithms.util.Indexer; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +/** + * @author Scott White + */ +public class TestUnweightedShortestPath extends TestCase +{ + private Supplier vertexFactory = + new Supplier() { + int count = 0; + public String get() { + return "V"+count++; + }}; + + private Supplier edgeFactory = + new Supplier() { + int count = 0; + public Integer get() { + return count++; + }}; + BiMap id; + + @Override + protected void setUp() { + } + public static Test suite() + { + return new TestSuite(TestUnweightedShortestPath.class); + } + + public void testUndirected() { + UndirectedGraph ug = + new UndirectedSparseMultigraph(); + for(int i=0; i<5; i++) { + ug.addVertex(vertexFactory.get()); + } + id = Indexer.create(ug.getVertices()); + +// GraphUtils.addVertices(ug,5); +// Indexer id = Indexer.getIndexer(ug); + ug.addEdge(edgeFactory.get(), id.inverse().get(0), id.inverse().get(1)); + ug.addEdge(edgeFactory.get(), id.inverse().get(1), id.inverse().get(2)); + ug.addEdge(edgeFactory.get(), id.inverse().get(2), id.inverse().get(3)); + ug.addEdge(edgeFactory.get(), id.inverse().get(0), id.inverse().get(4)); + ug.addEdge(edgeFactory.get(), id.inverse().get(4), id.inverse().get(3)); + + UnweightedShortestPath usp = + new UnweightedShortestPath(ug); + Assert.assertEquals(usp.getDistance(id.inverse().get(0),id.inverse().get(3)).intValue(),2); + Assert.assertEquals((usp.getDistanceMap(id.inverse().get(0)).get(id.inverse().get(3))).intValue(),2); + Assert.assertNull(usp.getIncomingEdgeMap(id.inverse().get(0)).get(id.inverse().get(0))); + Assert.assertNotNull(usp.getIncomingEdgeMap(id.inverse().get(0)).get(id.inverse().get(3))); + } + + public void testDirected() { + DirectedGraph dg = + new DirectedSparseMultigraph(); + for(int i=0; i<5; i++) { + dg.addVertex(vertexFactory.get()); + } + id = Indexer.create(dg.getVertices()); + dg.addEdge(edgeFactory.get(), id.inverse().get(0), id.inverse().get(1)); + dg.addEdge(edgeFactory.get(), id.inverse().get(1), id.inverse().get(2)); + dg.addEdge(edgeFactory.get(), id.inverse().get(2), id.inverse().get(3)); + dg.addEdge(edgeFactory.get(), id.inverse().get(0), id.inverse().get(4)); + dg.addEdge(edgeFactory.get(), id.inverse().get(4), id.inverse().get(3)); + dg.addEdge(edgeFactory.get(), id.inverse().get(3), id.inverse().get(0)); + + UnweightedShortestPath usp = + new UnweightedShortestPath(dg); + Assert.assertEquals(usp.getDistance(id.inverse().get(0),id.inverse().get(3)).intValue(),2); + Assert.assertEquals((usp.getDistanceMap(id.inverse().get(0)).get(id.inverse().get(3))).intValue(),2); + Assert.assertNull(usp.getIncomingEdgeMap(id.inverse().get(0)).get(id.inverse().get(0))); + Assert.assertNotNull(usp.getIncomingEdgeMap(id.inverse().get(0)).get(id.inverse().get(3))); + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/NotRandom.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/NotRandom.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/NotRandom.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/NotRandom.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,60 @@ +package edu.uci.ics.jung.algorithms.util; + +import java.util.Random; + +/** + * A decidedly non-random extension of {@code Random} that may be useful + * for testing random algorithms that accept an instance of {@code Random} + * as a parameter. This algorithm maintains internal counters which are + * incremented after each call, and returns values which are functions of + * those counter values. Thus the output is not only deterministic (as is + * necessarily true of all software with no externalities) but precisely + * predictable in distribution. + * + * @author Joshua O'Madadhain + */ +@SuppressWarnings("serial") +public class NotRandom extends Random +{ + private int i = 0; + private int d = 0; + private int size = 100; + + /** + * Creates an instance with the specified sample size. + * @param size the sample size + */ + public NotRandom(int size) + { + this.size = size; + } + + /** + * Returns the post-incremented value of the internal counter modulo n. + */ + @Override + public int nextInt(int n) + { + return i++ % n; + } + + /** + * Returns the post-incremented value of the internal counter modulo + * {@code size}, divided by {@code size}. + */ + @Override + public double nextDouble() + { + return (d++ % size) / (double)size; + } + + /** + * Returns the post-incremented value of the internal counter modulo + * {@code size}, divided by {@code size}. + */ + @Override + public float nextFloat() + { + return (d++ % size) / (float)size; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/TestWeightedChoice.java libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/TestWeightedChoice.java --- libjung-free-java-2.0.1+dfsg/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/TestWeightedChoice.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-algorithms/src/test/java/edu/uci/ics/jung/algorithms/util/TestWeightedChoice.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2009, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jan 13, 2009 + * + */ +package edu.uci.ics.jung.algorithms.util; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +/** + * @author jrtom + * + */ +public class TestWeightedChoice extends TestCase +{ + private WeightedChoice weighted_choice; + private Map item_weights = new HashMap(); + private Map item_counts = new HashMap(); + + @Override + public void tearDown() + { + item_weights.clear(); + item_counts.clear(); + } + + private void initializeWeights(double[] weights) + { + item_weights.put("a", weights[0]); + item_weights.put("b", weights[1]); + item_weights.put("c", weights[2]); + item_weights.put("d", weights[3]); + + for (String key : item_weights.keySet()) + item_counts.put(key, 0); + + } + + private void runWeightedChoice() + { + weighted_choice = new WeightedChoice(item_weights, new NotRandom(100)); + + int max_iterations = 10000; + for (int i = 0; i < max_iterations; i++) + { + String item = weighted_choice.nextItem(); + int count = item_counts.get(item); + item_counts.put(item, count+1); + } + + for (String key : item_weights.keySet()) + assertEquals((int)(item_weights.get(key) * max_iterations), + item_counts.get(key).intValue()); + } + + public void testUniform() + { + initializeWeights(new double[]{0.25, 0.25, 0.25, 0.25}); + + runWeightedChoice(); + } + + public void testNonUniform() + { + initializeWeights(new double[]{0.45, 0.10, 0.13, 0.32}); + + runWeightedChoice(); + } +} Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-algorithms-2.0.1-sources.jar and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-algorithms-2.0.1-sources.jar differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/assembly.xml libjung-free-java-2.1.1/jung-api/assembly.xml --- libjung-free-java-2.0.1+dfsg/jung-api/assembly.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/assembly.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + dependencies + + tar.gz + + false + + + / + + + + + / + false + runtime + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/pom.xml libjung-free-java-2.1.1/jung-api/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-api/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-api + JUNG - API + Graph interfaces used by the JUNG project + + + + com.google.guava + guava + + + junit + junit + test + + + + + + + + maven-jar-plugin + + + + test-jar + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/DirectedGraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/DirectedGraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/DirectedGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/DirectedGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,24 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +/** + * A tagging interface for implementations of Graph + * that accept only directed edges. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param type specification for vertices + * @param type specification for edges + */ +public interface DirectedGraph extends Graph { +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEvent.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEvent.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEvent.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,117 @@ +package edu.uci.ics.jung.graph.event; + +import edu.uci.ics.jung.graph.Graph; + +/** + * + * + * @author tom nelson + * + * @param the vertex type + * @param the edge type + */ +public abstract class GraphEvent { + + protected Graph source; + protected Type type; + + /** + * Creates an instance with the specified {@code source} graph and {@code Type} + * (vertex/edge addition/removal). + * + * @param source the graph whose event this is + * @param type the type of event this is + */ + public GraphEvent(Graph source, Type type) { + this.source = source; + this.type = type; + } + + /** + * Types of graph events. + */ + public static enum Type { + VERTEX_ADDED, + VERTEX_REMOVED, + EDGE_ADDED, + EDGE_REMOVED + } + + /** + * An event type pertaining to graph vertices. + */ + public static class Vertex extends GraphEvent { + protected V vertex; + + /** + * Creates a graph event for the specified graph, vertex, and type. + * + * @param source the graph whose event this is + * @param type the type of event this is + * @param vertex the vertex involved in this event + */ + public Vertex(Graph source, Type type, V vertex) { + super(source,type); + this.vertex = vertex; + } + + /** + * @return the vertex associated with this event + */ + public V getVertex() { + return vertex; + } + + @Override + public String toString() { + return "GraphEvent type:"+type+" for "+vertex; + } + + } + + /** + * An event type pertaining to graph edges. + */ + public static class Edge extends GraphEvent { + protected E edge; + + /** + * Creates a graph event for the specified graph, edge, and type. + * + * @param source the graph whose event this is + * @param type the type of event this is + * @param edge the edge involved in this event + */ + public Edge(Graph source, Type type, E edge) { + super(source,type); + this.edge = edge; + } + + /** + * @return the edge associated with this event. + */ + public E getEdge() { + return edge; + } + + @Override + public String toString() { + return "GraphEvent type:"+type+" for "+edge; + } + + } + + /** + * @return the source + */ + public Graph getSource() { + return source; + } + + /** + * @return the type + */ + public Type getType() { + return type; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEventListener.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEventListener.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEventListener.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/GraphEventListener.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,18 @@ +package edu.uci.ics.jung.graph.event; + +import java.util.EventListener; + +/** + * An interface for classes that listen for graph events. + */ +public interface GraphEventListener extends EventListener +{ + /** + * Method called by the process generating a graph event to which + * this instance is listening. The implementor of this interface + * is responsible for deciding what behavior is appropriate. + * + * @param evt the graph event to be handled + */ + void handleGraphEvent(GraphEvent evt); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/package.html libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/package.html --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/event/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/event/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

    Support for generating events in response to graph actions, especially mutations. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Forest.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Forest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Forest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Forest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,96 @@ +package edu.uci.ics.jung.graph; + +import java.util.Collection; + +/** + * An interface for a graph which consists of a collection of rooted + * directed acyclic graphs. + * + * @author Joshua O'Madadhain + */ +public interface Forest extends DirectedGraph { + + /** + * Returns a view of this graph as a collection of Tree instances. + * @return a view of this graph as a collection of Trees + */ + Collection> getTrees(); + + /** + * Returns the parent of vertex in this tree. + * (If vertex is the root, returns null.) + * The parent of a vertex is defined as being its predecessor in the + * (unique) shortest path from the root to this vertex. + * This is a convenience method which is equivalent to + * Graph.getPredecessors(vertex).iterator().next(). + * + * @param vertex the vertex whose parent is to be returned + * @return the parent of vertex in this tree + * @see Graph#getPredecessors(Object) + * @see #getParentEdge(Object) + */ + public V getParent(V vertex); + + /** + * Returns the edge connecting vertex to its parent in + * this tree. + * (If vertex is the root, returns null.) + * The parent of a vertex is defined as being its predecessor in the + * (unique) shortest path from the root to this vertex. + * This is a convenience method which is equivalent to + * Graph.getInEdges(vertex).iterator().next(), + * and also to Graph.findEdge(vertex, getParent(vertex)). + * + * @param vertex the vertex whose incoming edge is to be returned + * @return the edge connecting vertex to its parent, or + * null if vertex is the root + * + * @see Graph#getInEdges(Object) + * @see #getParent(Object) + */ + public E getParentEdge(V vertex); + + /** + * Returns the children of vertex in this tree. + * The children of a vertex are defined as being the successors of + * that vertex on the respective (unique) shortest paths from the root to + * those vertices. + * This is syntactic (maple) sugar for getSuccessors(vertex). + * @param vertex the vertex whose children are to be returned + * @return the Collection of children of vertex + * in this tree + * @see Graph#getSuccessors(Object) + * @see #getChildEdges(Object) + */ + public Collection getChildren(V vertex); + + /** + * Returns the edges connecting vertex to its children + * in this tree. + * The children of a vertex are defined as being the successors of + * that vertex on the respective (unique) shortest paths from the root to + * those vertices. + * This is syntactic (maple) sugar for getOutEdges(vertex). + * @param vertex the vertex whose child edges are to be returned + * @return the Collection of edges connecting + * vertex to its children in this tree + * @see Graph#getOutEdges(Object) + * @see #getChildren(Object) + */ + public Collection getChildEdges(V vertex); + + /** + * Returns the number of children that vertex has in this tree. + * The children of a vertex are defined as being the successors of + * that vertex on the respective (unique) shortest paths from the root to + * those vertices. + * This is syntactic (maple) sugar for getSuccessorCount(vertex). + * @param vertex the vertex whose child edges are to be returned + * @return the Collection of edges connecting + * vertex to its children in this tree + * @see #getChildEdges(Object) + * @see #getChildren(Object) + * @see Graph#getSuccessorCount(Object) + */ + public int getChildCount(V vertex); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/GraphDecorator.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/GraphDecorator.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/GraphDecorator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/GraphDecorator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,332 @@ +package edu.uci.ics.jung.graph; + +import java.io.Serializable; +import java.util.Collection; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Graph that delegates its method calls to a + * constructor-specified Graph instance. This is useful for adding + * additional behavior (such as synchronization or unmodifiability) to an existing + * instance. + */ +@SuppressWarnings("serial") +public class GraphDecorator implements Graph, Serializable { + + protected Graph delegate; + + /** + * Creates a new instance based on the provided {@code delegate}. + * @param delegate the graph to which method calls will be delegated + */ + public GraphDecorator(Graph delegate) { + this.delegate = delegate; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection) + */ + public boolean addEdge(E edge, Collection vertices) { + return delegate.addEdge(edge, vertices); + } + + /** + * @see Hypergraph#addEdge(Object, Collection, EdgeType) + */ + public boolean addEdge(E edge, Collection vertices, EdgeType + edge_type) + { + return delegate.addEdge(edge, vertices, edge_type); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType) + */ + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + return delegate.addEdge(e, v1, v2, edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object) + */ + public boolean addEdge(E e, V v1, V v2) { + return delegate.addEdge(e, v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object) + */ + public boolean addVertex(V vertex) { + return delegate.addVertex(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isIncident(java.lang.Object, java.lang.Object) + */ + public boolean isIncident(V vertex, E edge) { + return delegate.isIncident(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isNeighbor(java.lang.Object, java.lang.Object) + */ + public boolean isNeighbor(V v1, V v2) { + return delegate.isNeighbor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#degree(java.lang.Object) + */ + public int degree(V vertex) { + return delegate.degree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdge(java.lang.Object, java.lang.Object) + */ + public E findEdge(V v1, V v2) { + return delegate.findEdge(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdgeSet(java.lang.Object, java.lang.Object) + */ + public Collection findEdgeSet(V v1, V v2) { + return delegate.findEdgeSet(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDest(java.lang.Object) + */ + public V getDest(E directed_edge) { + return delegate.getDest(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount() + */ + public int getEdgeCount() { + return delegate.getEdgeCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount(EdgeType) + */ + public int getEdgeCount(EdgeType edge_type) + { + return delegate.getEdgeCount(edge_type); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdges() + */ + public Collection getEdges() { + return delegate.getEdges(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdges(edu.uci.ics.jung.graph.util.EdgeType) + */ + public Collection getEdges(EdgeType edgeType) { + return delegate.getEdges(edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdgeType(java.lang.Object) + */ + public EdgeType getEdgeType(E edge) { + return delegate.getEdgeType(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDefaultEdgeType() + */ + public EdgeType getDefaultEdgeType() + { + return delegate.getDefaultEdgeType(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEndpoints(java.lang.Object) + */ + public Pair getEndpoints(E edge) { + return delegate.getEndpoints(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentCount(java.lang.Object) + */ + public int getIncidentCount(E edge) { + return delegate.getIncidentCount(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentEdges(java.lang.Object) + */ + public Collection getIncidentEdges(V vertex) { + return delegate.getIncidentEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentVertices(java.lang.Object) + */ + public Collection getIncidentVertices(E edge) { + return delegate.getIncidentVertices(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getInEdges(java.lang.Object) + */ + public Collection getInEdges(V vertex) { + return delegate.getInEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighborCount(java.lang.Object) + */ + public int getNeighborCount(V vertex) { + return delegate.getNeighborCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighbors(java.lang.Object) + */ + public Collection getNeighbors(V vertex) { + return delegate.getNeighbors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOpposite(java.lang.Object, java.lang.Object) + */ + public V getOpposite(V vertex, E edge) { + return delegate.getOpposite(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOutEdges(java.lang.Object) + */ + public Collection getOutEdges(V vertex) { + return delegate.getOutEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessorCount(java.lang.Object) + */ + public int getPredecessorCount(V vertex) { + return delegate.getPredecessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessors(java.lang.Object) + */ + public Collection getPredecessors(V vertex) { + return delegate.getPredecessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSource(java.lang.Object) + */ + public V getSource(E directed_edge) { + return delegate.getSource(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessorCount(java.lang.Object) + */ + public int getSuccessorCount(V vertex) { + return delegate.getSuccessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessors(java.lang.Object) + */ + public Collection getSuccessors(V vertex) { + return delegate.getSuccessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertexCount() + */ + public int getVertexCount() { + return delegate.getVertexCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertices() + */ + public Collection getVertices() { + return delegate.getVertices(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#inDegree(java.lang.Object) + */ + public int inDegree(V vertex) { + return delegate.inDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isDest(java.lang.Object, java.lang.Object) + */ + public boolean isDest(V vertex, E edge) { + return delegate.isDest(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isPredecessor(java.lang.Object, java.lang.Object) + */ + public boolean isPredecessor(V v1, V v2) { + return delegate.isPredecessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSource(java.lang.Object, java.lang.Object) + */ + public boolean isSource(V vertex, E edge) { + return delegate.isSource(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSuccessor(java.lang.Object, java.lang.Object) + */ + public boolean isSuccessor(V v1, V v2) { + return delegate.isSuccessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#outDegree(java.lang.Object) + */ + public int outDegree(V vertex) { + return delegate.outDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + public boolean removeEdge(E edge) { + return delegate.removeEdge(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + public boolean removeVertex(V vertex) { + return delegate.removeVertex(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsEdge(java.lang.Object) + */ + public boolean containsEdge(E edge) { + return delegate.containsEdge(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsVertex(java.lang.Object) + */ + public boolean containsVertex(V vertex) { + return delegate.containsVertex(vertex); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Graph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Graph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Graph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Graph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,247 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * A graph consisting of a set of vertices of type V + * set and a set of edges of type E. Edges of this + * graph type have exactly two endpoints; whether these endpoints + * must be distinct depends on the implementation. + *

    + * This interface permits, but does not enforce, any of the following + * common variations of graphs: + *

      + *
    • directed and undirected edges + *
    • vertices and edges with attributes (for example, weighted edges) + *
    • vertices and edges of different types (for example, bipartite + * or multimodal graphs) + *
    • parallel edges (multiple edges which connect a single set of vertices) + *
    • representations as matrices or as adjacency lists or adjacency maps + *
    + * Extensions or implementations of this interface + * may enforce or disallow any or all of these variations. + * + *

    Definitions (with respect to a given vertex v): + *

      + *
    • incoming edge of v: an edge that can be traversed + * from a neighbor of v to reach v + *
    • outgoing edge of v: an edge that can be traversed + * from v to reach some neighbor of v + *
    • predecessor of v: a vertex at the other end of an + * incoming edge of v + *
    • successor of v: a vertex at the other end of an + * outgoing edge of v + *
    • + *
    + * + * @author Joshua O'Madadhain + */ +public interface Graph extends Hypergraph +{ + /** + * Returns a Collection view of the incoming edges incident to vertex + * in this graph. + * @param vertex the vertex whose incoming edges are to be returned + * @return a Collection view of the incoming edges incident + * to vertex in this graph + */ + Collection getInEdges(V vertex); + + /** + * Returns a Collection view of the outgoing edges incident to vertex + * in this graph. + * @param vertex the vertex whose outgoing edges are to be returned + * @return a Collection view of the outgoing edges incident + * to vertex in this graph + */ + Collection getOutEdges(V vertex); + + /** + * Returns a Collection view of the predecessors of vertex + * in this graph. A predecessor of vertex is defined as a vertex v + * which is connected to + * vertex by an edge e, where e is an outgoing edge of + * v and an incoming edge of vertex. + * @param vertex the vertex whose predecessors are to be returned + * @return a Collection view of the predecessors of + * vertex in this graph + */ + Collection getPredecessors(V vertex); + + /** + * Returns a Collection view of the successors of vertex + * in this graph. A successor of vertex is defined as a vertex v + * which is connected to + * vertex by an edge e, where e is an incoming edge of + * v and an outgoing edge of vertex. + * @param vertex the vertex whose predecessors are to be returned + * @return a Collection view of the successors of + * vertex in this graph + */ + Collection getSuccessors(V vertex); + + /** + * Returns the number of incoming edges incident to vertex. + * Equivalent to getInEdges(vertex).size(). + * @param vertex the vertex whose indegree is to be calculated + * @return the number of incoming edges incident to vertex + */ + int inDegree(V vertex); + + /** + * Returns the number of outgoing edges incident to vertex. + * Equivalent to getOutEdges(vertex).size(). + * @param vertex the vertex whose outdegree is to be calculated + * @return the number of outgoing edges incident to vertex + */ + int outDegree(V vertex); + + /** + * Returns true if v1 is a predecessor of v2 in this graph. + * Equivalent to v1.getPredecessors().contains(v2). + * @param v1 the first vertex to be queried + * @param v2 the second vertex to be queried + * @return true if v1 is a predecessor of v2, and false otherwise. + */ + boolean isPredecessor(V v1, V v2); + + /** + * Returns true if v1 is a successor of v2 in this graph. + * Equivalent to v1.getSuccessors().contains(v2). + * @param v1 the first vertex to be queried + * @param v2 the second vertex to be queried + * @return true if v1 is a successor of v2, and false otherwise. + */ + boolean isSuccessor(V v1, V v2); + + /** + * Returns the number of predecessors that vertex has in this graph. + * Equivalent to vertex.getPredecessors().size(). + * @param vertex the vertex whose predecessor count is to be returned + * @return the number of predecessors that vertex has in this graph + */ + int getPredecessorCount(V vertex); + + /** + * Returns the number of successors that vertex has in this graph. + * Equivalent to vertex.getSuccessors().size(). + * @param vertex the vertex whose successor count is to be returned + * @return the number of successors that vertex has in this graph + */ + int getSuccessorCount(V vertex); + + /** + * If directed_edge is a directed edge in this graph, returns the source; + * otherwise returns null. + * The source of a directed edge d is defined to be the vertex for which + * d is an outgoing edge. + * directed_edge is guaranteed to be a directed edge if + * its EdgeType is DIRECTED. + * @param directed_edge the edge whose source is to be returned + * @return the source of directed_edge if it is a directed edge in this graph, or null otherwise + */ + V getSource(E directed_edge); + + /** + * If directed_edge is a directed edge in this graph, returns the destination; + * otherwise returns null. + * The destination of a directed edge d is defined to be the vertex + * incident to d for which + * d is an incoming edge. + * directed_edge is guaranteed to be a directed edge if + * its EdgeType is DIRECTED. + * @param directed_edge the edge whose destination is to be returned + * @return the destination of directed_edge if it is a directed edge in this graph, or null otherwise + */ + V getDest(E directed_edge); + + /** + * Returns true if vertex is the source of edge. + * Equivalent to getSource(edge).equals(vertex). + * @param vertex the vertex to be queried + * @param edge the edge to be queried + * @return true iff vertex is the source of edge + */ + boolean isSource(V vertex, E edge); + + /** + * Returns true if vertex is the destination of edge. + * Equivalent to getDest(edge).equals(vertex). + * @param vertex the vertex to be queried + * @param edge the edge to be queried + * @return true iff vertex is the destination of edge + */ + boolean isDest(V vertex, E edge); + + /** + * Adds edge e to this graph such that it connects + * vertex v1 to v2. + * Equivalent to addEdge(e, new Pair(v1, v2)). + * If this graph does not contain v1, v2, + * or both, implementations may choose to either silently add + * the vertices to the graph or throw an IllegalArgumentException. + * If this graph assigns edge types to its edges, the edge type of + * e will be the default for this graph. + * See Hypergraph.addEdge() for a listing of possible reasons + * for failure. + * @param e the edge to be added + * @param v1 the first vertex to be connected + * @param v2 the second vertex to be connected + * @return true if the add is successful, false otherwise + * @see Hypergraph#addEdge(Object, Collection) + * @see #addEdge(Object, Object, Object, EdgeType) + */ + boolean addEdge(E e, V v1, V v2); + + /** + * Adds edge e to this graph such that it connects + * vertex v1 to v2. + * Equivalent to addEdge(e, new Pair(v1, v2)). + * If this graph does not contain v1, v2, + * or both, implementations may choose to either silently add + * the vertices to the graph or throw an IllegalArgumentException. + * If edgeType is not legal for this graph, this method will + * throw IllegalArgumentException. + * See Hypergraph.addEdge() for a listing of possible reasons + * for failure. + * @param e the edge to be added + * @param v1 the first vertex to be connected + * @param v2 the second vertex to be connected + * @param edgeType the type to be assigned to the edge + * @return true if the add is successful, false otherwise + * @see Hypergraph#addEdge(Object, Collection) + * @see #addEdge(Object, Object, Object) + */ + boolean addEdge(E e, V v1, V v2, EdgeType edgeType); + + /** + * Returns the endpoints of edge as a Pair. + * @param edge the edge whose endpoints are to be returned + * @return the endpoints (incident vertices) of edge + */ + Pair getEndpoints(E edge); + + /** + * Returns the vertex at the other end of edge from vertex. + * (That is, returns the vertex incident to edge which is not vertex.) + * @param vertex the vertex to be queried + * @param edge the edge to be queried + * @return the vertex at the other end of edge from vertex + */ + V getOpposite(V vertex, E edge); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Hypergraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Hypergraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Hypergraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Hypergraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,442 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; + +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * A hypergraph, consisting of a set of vertices of type V + * and a set of hyperedges of type E which connect the vertices. + * This is the base interface for all JUNG graph types. + *

    + * This interface permits, but does not enforce, any of the following + * common variations of graphs: + *

      + *
    • hyperedges (edges which connect a set of vertices of any size) + *
    • edges (these have have exactly two endpoints, which may or may not be distinct) + *
    • self-loops (edges which connect exactly one vertex) + *
    • directed and undirected edges + *
    • vertices and edges with attributes (for example, weighted edges) + *
    • vertices and edges with different constraints or properties (for example, bipartite + * or multimodal graphs) + *
    • parallel edges (multiple edges which connect a single set of vertices) + *
    • internal representations as matrices or as adjacency lists or adjacency maps + *
    + * Extensions or implementations of this interface + * may enforce or disallow any or all of these variations. + *

    Notes: + *

      + *
    • The collections returned by Hypergraph instances + * should be treated in general as if read-only. While they are not contractually + * guaranteed (or required) to be immutable, + * this interface does not define the outcome if they are mutated. + * Mutations should be done via {add,remove}{Edge,Vertex}, or + * in the constructor. + *
    • + *
    + * + * @author Joshua O'Madadhain + */ +public interface Hypergraph +{ + /** + * Returns a view of all edges in this graph. In general, this + * obeys the Collection contract, and therefore makes no guarantees + * about the ordering of the vertices within the set. + * @return a Collection view of all edges in this graph + */ + Collection getEdges(); + + /** + * Returns a view of all vertices in this graph. In general, this + * obeys the Collection contract, and therefore makes no guarantees + * about the ordering of the vertices within the set. + * @return a Collection view of all vertices in this graph + */ + Collection getVertices(); + + /** + * Returns true if this graph's vertex collection contains vertex. + * Equivalent to getVertices().contains(vertex). + * @param vertex the vertex whose presence is being queried + * @return true iff this graph contains a vertex vertex + */ + boolean containsVertex(V vertex); + + /** + * Returns true if this graph's edge collection contains edge. + * Equivalent to getEdges().contains(edge). + * @param edge the edge whose presence is being queried + * @return true iff this graph contains an edge edge + */ + boolean containsEdge(E edge); + + /** + * Returns the number of edges in this graph. + * @return the number of edges in this graph + */ + int getEdgeCount(); + + /** + * Returns the number of vertices in this graph. + * @return the number of vertices in this graph + */ + int getVertexCount(); + + /** + * Returns the collection of vertices which are connected to vertex + * via any edges in this graph. + * If vertex is connected to itself with a self-loop, then + * it will be included in the collection returned. + * + * @param vertex the vertex whose neighbors are to be returned + * @return the collection of vertices which are connected to vertex, + * or null if vertex is not present + */ + Collection getNeighbors(V vertex); + + /** + * Returns the collection of edges in this graph which are connected to vertex. + * + * @param vertex the vertex whose incident edges are to be returned + * @return the collection of edges which are connected to vertex, + * or null if vertex is not present + */ + Collection getIncidentEdges(V vertex); + + /** + * Returns the collection of vertices in this graph which are connected to edge. + * Note that for some graph types there are guarantees about the size of this collection + * (i.e., some graphs contain edges that have exactly two endpoints, which may or may + * not be distinct). Implementations for those graph types may provide alternate methods + * that provide more convenient access to the vertices. + * + * @param edge the edge whose incident vertices are to be returned + * @return the collection of vertices which are connected to edge, + * or null if edge is not present + */ + Collection getIncidentVertices(E edge); + + /** + * Returns an edge that connects this vertex to v. + * If this edge is not uniquely + * defined (that is, if the graph contains more than one edge connecting + * v1 to v2), any of these edges + * may be returned. findEdgeSet(v1, v2) may be + * used to return all such edges. + * Returns null if either of the following is true: + *
      + *
    • v2 is not connected to v1 + *
    • either v1 or v2 are not present in this graph + *
    + *

    Note: for purposes of this method, v1 is only considered to be connected to + * v2 via a given directed edge e if + * v1 == e.getSource() && v2 == e.getDest() evaluates to true. + * (v1 and v2 are connected by an undirected edge u if + * u is incident to both v1 and v2.) + * + * @param v1 the first endpoint of the returned edge + * @param v2 the second endpoint of the returned edge + * @return an edge that connects v1 to v2, + * or null if no such edge exists (or either vertex is not present) + * @see Hypergraph#findEdgeSet(Object, Object) + */ + E findEdge(V v1, V v2); + + /** + * Returns all edges that connects this vertex to v. + * If this edge is not uniquely + * defined (that is, if the graph contains more than one edge connecting + * v1 to v2), any of these edges + * may be returned. findEdgeSet(v1, v2) may be + * used to return all such edges. + * Returns null if v2 is not connected to v1. + *
    Returns an empty collection if either v1 or v2 + * are not present in this graph. + * + *

    Note: for purposes of this method, v1 is only considered to be connected to + * v2 via a given directed edge d if + * v1 == d.getSource() && v2 == d.getDest() evaluates to true. + * (v1 and v2 are connected by an undirected edge u if + * u is incident to both v1 and v2.) + * + * @param v1 the first endpoint of the returned edge set + * @param v2 the second endpoint of the returned edge set + * @return a collection containing all edges that connect v1 to v2, + * or null if either vertex is not present + * @see Hypergraph#findEdge(Object, Object) + */ + Collection findEdgeSet(V v1, V v2); + + /** + * Adds vertex to this graph. + * Fails if vertex is null or already in the graph. + * + * @param vertex the vertex to add + * @return true if the add is successful, and false otherwise + * @throws IllegalArgumentException if vertex is null + */ + boolean addVertex(V vertex); + + /** + * Adds edge to this graph. + * Fails under the following circumstances: + *

      + *
    • edge is already an element of the graph + *
    • either edge or vertices is null + *
    • vertices has the wrong number of vertices for the graph type + *
    • vertices are already connected by another edge in this graph, + * and this graph does not accept parallel edges + *
    + * + * @param edge the edge to add + * @param vertices the vertices to which the edge will be connected + * @return true if the add is successful, and false otherwise + * @throws IllegalArgumentException if edge or vertices is null, + * or if a different vertex set in this graph is already connected by edge, + * or if vertices are not a legal vertex set for edge + */ + boolean addEdge(E edge, Collection vertices); + + /** + * Adds edge to this graph with type edge_type. + * Fails under the following circumstances: + *
      + *
    • edge is already an element of the graph + *
    • either edge or vertices is null + *
    • vertices has the wrong number of vertices for the graph type + *
    • vertices are already connected by another edge in this graph, + * and this graph does not accept parallel edges + *
    • edge_type is not legal for this graph + *
    + * + * @param edge edge to add to this graph + * @param vertices vertices which are to be connected by this edge + * @param edge_type type of edge to add + * @return true if the add is successful, and false otherwise + * @throws IllegalArgumentException if edge or vertices is null, + * or if a different vertex set in this graph is already connected by edge, + * or if vertices are not a legal vertex set for edge + */ + boolean addEdge(E edge, Collection vertices, EdgeType + edge_type); + + /** + * Removes vertex from this graph. + * As a side effect, removes any edges e incident to vertex if the + * removal of vertex would cause e to be incident to an illegal + * number of vertices. (Thus, for example, incident hyperedges are not removed, but + * incident edges--which must be connected to a vertex at both endpoints--are removed.) + * + *

    Fails under the following circumstances: + *

      + *
    • vertex is not an element of this graph + *
    • vertex is null + *
    + * + * @param vertex the vertex to remove + * @return true if the removal is successful, false otherwise + */ + boolean removeVertex(V vertex); + + /** + * Removes edge from this graph. + * Fails if edge is null, or is otherwise not an element of this graph. + * + * @param edge the edge to remove + * @return true if the removal is successful, false otherwise + */ + boolean removeEdge(E edge); + + + /** + * Returns true if v1 and v2 share an incident edge. + * Equivalent to getNeighbors(v1).contains(v2). + * + * @param v1 the first vertex to test + * @param v2 the second vertex to test + * @return true if v1 and v2 share an incident edge + */ + boolean isNeighbor(V v1, V v2); + + /** + * Returns true if vertex and edge + * are incident to each other. + * Equivalent to getIncidentEdges(vertex).contains(edge) and to + * getIncidentVertices(edge).contains(vertex). + * @param vertex vertex to test + * @param edge edge to test + * @return true if vertex and edge + * are incident to each other + */ + boolean isIncident(V vertex, E edge); + + /** + * Returns the number of edges incident to vertex. + * Special cases of interest: + *
      + *
    • Incident self-loops are counted once. + *
    • If there is only one edge that connects this vertex to + * each of its neighbors (and vice versa), then the value returned + * will also be equal to the number of neighbors that this vertex has + * (that is, the output of getNeighborCount). + *
    • If the graph is directed, then the value returned will be + * the sum of this vertex's indegree (the number of edges whose + * destination is this vertex) and its outdegree (the number + * of edges whose source is this vertex), minus the number of + * incident self-loops (to avoid double-counting). + *
    + *

    Equivalent to getIncidentEdges(vertex).size(). + * + * @param vertex the vertex whose degree is to be returned + * @return the degree of this node + * @see Hypergraph#getNeighborCount(Object) + */ + int degree(V vertex); + + /** + * Returns the number of vertices that are adjacent to vertex + * (that is, the number of vertices that are incident to edges in vertex's + * incident edge set). + * + *

    Equivalent to getNeighbors(vertex).size(). + * @param vertex the vertex whose neighbor count is to be returned + * @return the number of neighboring vertices + */ + int getNeighborCount(V vertex); + + /** + * Returns the number of vertices that are incident to edge. + * For hyperedges, this can be any nonnegative integer; for edges this + * must be 2 (or 1 if self-loops are permitted). + * + *

    Equivalent to getIncidentVertices(edge).size(). + * @param edge the edge whose incident vertex count is to be returned + * @return the number of vertices that are incident to edge. + */ + int getIncidentCount(E edge); + + /** + * Returns the edge type of edge in this graph. + * @param edge the edge whose type is to be returned + * @return the EdgeType of edge, or null if edge has no defined type + */ + EdgeType getEdgeType(E edge); + + /** + * Returns the default edge type for this graph. + * + * @return the default edge type for this graph + */ + EdgeType getDefaultEdgeType(); + + /** + * Returns the collection of edges in this graph which are of type edge_type. + * @param edge_type the type of edges to be returned + * @return the collection of edges which are of type edge_type, or + * null if the graph does not accept edges of this type + * @see EdgeType + */ + Collection getEdges(EdgeType edge_type); + + /** + * Returns the number of edges of type edge_type in this graph. + * @param edge_type the type of edge for which the count is to be returned + * @return the number of edges of type edge_type in this graph + */ + int getEdgeCount(EdgeType edge_type); + + /** + * Returns a Collection view of the incoming edges incident to vertex + * in this graph. + * @param vertex the vertex whose incoming edges are to be returned + * @return a Collection view of the incoming edges incident + * to vertex in this graph + */ + Collection getInEdges(V vertex); + + /** + * Returns a Collection view of the outgoing edges incident to vertex + * in this graph. + * @param vertex the vertex whose outgoing edges are to be returned + * @return a Collection view of the outgoing edges incident + * to vertex in this graph + */ + Collection getOutEdges(V vertex); + + /** + * Returns the number of incoming edges incident to vertex. + * Equivalent to getInEdges(vertex).size(). + * @param vertex the vertex whose indegree is to be calculated + * @return the number of incoming edges incident to vertex + */ + int inDegree(V vertex); + + /** + * Returns the number of outgoing edges incident to vertex. + * Equivalent to getOutEdges(vertex).size(). + * @param vertex the vertex whose outdegree is to be calculated + * @return the number of outgoing edges incident to vertex + */ + int outDegree(V vertex); + + /** + * If directed_edge is a directed edge in this graph, returns the source; + * otherwise returns null. + * The source of a directed edge d is defined to be the vertex for which + * d is an outgoing edge. + * directed_edge is guaranteed to be a directed edge if + * its EdgeType is DIRECTED. + * @param directed_edge the edge whose source is to be returned + * @return the source of directed_edge if it is a directed edge in this graph, or null otherwise + */ + V getSource(E directed_edge); + + /** + * If directed_edge is a directed edge in this graph, returns the destination; + * otherwise returns null. + * The destination of a directed edge d is defined to be the vertex + * incident to d for which + * d is an incoming edge. + * directed_edge is guaranteed to be a directed edge if + * its EdgeType is DIRECTED. + * @param directed_edge the edge whose destination is to be returned + * @return the destination of directed_edge if it is a directed edge in this graph, or null otherwise + */ + V getDest(E directed_edge); + + /** + * Returns a Collection view of the predecessors of vertex + * in this graph. A predecessor of vertex is defined as a vertex v + * which is connected to + * vertex by an edge e, where e is an outgoing edge of + * v and an incoming edge of vertex. + * @param vertex the vertex whose predecessors are to be returned + * @return a Collection view of the predecessors of + * vertex in this graph + */ + Collection getPredecessors(V vertex); + + /** + * Returns a Collection view of the successors of vertex + * in this graph. A successor of vertex is defined as a vertex v + * which is connected to + * vertex by an edge e, where e is an incoming edge of + * v and an outgoing edge of vertex. + * @param vertex the vertex whose predecessors are to be returned + * @return a Collection view of the successors of + * vertex in this graph + */ + Collection getSuccessors(V vertex); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/KPartiteGraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/KPartiteGraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/KPartiteGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/KPartiteGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Created on May 24, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; + +import com.google.common.base.Predicate; + +/** + * An interface for graphs whose vertices are each members of one of 2 or more + * disjoint sets (partitions), and whose edges connect only vertices in distinct + * partitions. + * + * @author Joshua O'Madadhain + */ +public interface KPartiteGraph extends Graph +{ + /** + * Returns all vertices which satisfy the specified partition predicate. + * @param partition Predicate which defines a partition + * @return all vertices satisfying partition + */ + public Collection getVertices(Predicate partition); + + /** + * Returns the set of Predicate instances which define this graph's partitions. + * @return the set of Predicate instances which define this graph's partitions + */ + public Collection> getPartitions(); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/MultiGraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/MultiGraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/MultiGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/MultiGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ +/* + * Created on Aug 31, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +/** + * A tagging interface which indicates that the implementing graph accepts + * parallel edges. + * + * @author Joshua O'Madadhain + */ +public interface MultiGraph {} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/ObservableGraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/ObservableGraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/ObservableGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/ObservableGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,142 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import edu.uci.ics.jung.graph.event.GraphEvent; +import edu.uci.ics.jung.graph.event.GraphEventListener; +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * A decorator class for graphs which generates events + * + * @author Joshua O'Madadhain + */ +@SuppressWarnings("serial") +public class ObservableGraph extends GraphDecorator { + + List> listenerList = + Collections.synchronizedList(new LinkedList>()); + + /** + * Creates a new instance based on the provided {@code delegate}. + * + * @param delegate the graph on which this class operates + */ + public ObservableGraph(Graph delegate) { + super(delegate); + } + + /** + * Adds {@code l} as a listener to this graph. + * + * @param l the listener to add + */ + public void addGraphEventListener(GraphEventListener l) { + listenerList.add(l); + } + + /** + * Removes {@code l} as a listener to this graph. + * + * @param l the listener to remove + */ + public void removeGraphEventListener(GraphEventListener l) { + listenerList.remove(l); + } + + protected void fireGraphEvent(GraphEvent evt) { + for(GraphEventListener listener : listenerList) { + listener.handleGraphEvent(evt); + } + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection) + */ + @Override + public boolean addEdge(E edge, Collection vertices) { + boolean state = super.addEdge(edge, vertices); + if(state) { + GraphEvent evt = new GraphEvent.Edge(delegate, GraphEvent.Type.EDGE_ADDED, edge); + fireGraphEvent(evt); + } + return state; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType) + */ + @Override + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + boolean state = super.addEdge(e, v1, v2, edgeType); + if(state) { + GraphEvent evt = new GraphEvent.Edge(delegate, GraphEvent.Type.EDGE_ADDED, e); + fireGraphEvent(evt); + } + return state; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object) + */ + @Override + public boolean addEdge(E e, V v1, V v2) { + boolean state = super.addEdge(e, v1, v2); + if(state) { + GraphEvent evt = new GraphEvent.Edge(delegate, GraphEvent.Type.EDGE_ADDED, e); + fireGraphEvent(evt); + } + return state; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object) + */ + @Override + public boolean addVertex(V vertex) { + boolean state = super.addVertex(vertex); + if(state) { + GraphEvent evt = new GraphEvent.Vertex(delegate, GraphEvent.Type.VERTEX_ADDED, vertex); + fireGraphEvent(evt); + } + return state; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + @Override + public boolean removeEdge(E edge) { + boolean state = delegate.removeEdge(edge); + if(state) { + GraphEvent evt = new GraphEvent.Edge(delegate, GraphEvent.Type.EDGE_REMOVED, edge); + fireGraphEvent(evt); + } + return state; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + @Override + public boolean removeVertex(V vertex) { + // remove all incident edges first, so that the appropriate events will + // be fired (otherwise they'll be removed inside {@code delegate.removeVertex} + // and the events will not be fired) + Collection incident_edges = new ArrayList(delegate.getIncidentEdges(vertex)); + for (E e : incident_edges) + this.removeEdge(e); + + boolean state = delegate.removeVertex(vertex); + if(state) { + GraphEvent evt = new GraphEvent.Vertex(delegate, GraphEvent.Type.VERTEX_REMOVED, vertex); + fireGraphEvent(evt); + } + return state; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/package.html libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/package.html --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + + + +

    Interfaces for the JUNG graph types, and some representative implementations. + +

    A graph consists of a set of vertices set and a set of edges which connect the +vertices. The base interface is Hypergraph, which defines the most +general type of graph; other interfaces (Graph, DirectedGraph, etc.) +define more restrictive graph types. +

    Vertex and edge types are specified at compile type using Java 1.5 generics. + +

    Types of graphs which are supported include (but are not limited to) +

      +
    • edges (these have have exactly two endpoints, which may or may not be distinct) +
    • self-loops (edges which connect exactly one vertex) +
    • directed and undirected edges +
    • vertices and edges with attributes (for example, weighted edges) +
    • vertices and edges with different constraints or properties (examples: trees, bipartite + graphs, or multimodal) +
    • parallel edges (multiple edges which connect a single set of vertices) +
    • internal representations as matrices or as adjacency lists or adjacency maps +
    • internal representations that order their elements according to insertion time, +natural ordering, or a specified Comparator +
    +Extensions or implementations of this interface +may enforce or disallow any or all of these variations. +

    Notes: +

      +
    • The collections returned by graph instances +should be treated in general as if read-only. While they are not contractually +guaranteed (or required) to be immutable, +these interfaces do not define the outcome if they are mutated. +Mutations should be done via {add,remove}{Edge,Vertex}, or +in the constructor. +
    • "Wrapper" graphs are available through GraphDecorator; these are useful +if you want to create a graph implementation that uses another implementation to do the work, +and adds some extra behavior. (One example: ObservableGraph, which notifies +registered listeners when graph mutations occur.) +
    + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Tree.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Tree.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/Tree.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/Tree.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Created on Feb 3, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + + +/** + * A subtype of Graph which is a (directed, rooted) tree. + * What we refer to as a "tree" here is actually (in the terminology of graph theory) a + * rooted tree. (That is, there is a designated single vertex--the root--from which we measure + * the shortest path to each vertex, which we call its depth; the maximum over all such + * depths is the tree's height. Note that for a tree, there is exactly + * one unique path from the root to any vertex.) + * + * @author Joshua O'Madadhain + */ +public interface Tree extends Forest +{ + /** + * Returns the (unweighted) distance of vertex + * from the root of this tree. + * @param vertex the vertex whose depth is to be returned. + * @return the length of the shortest unweighted path + * from vertex to the root of this tree + * @see #getHeight() + */ + public int getDepth(V vertex); + + /** + * Returns the maximum depth in this tree. + * @return the maximum depth in this tree + * @see #getDepth(Object) + */ + public int getHeight(); + + /** + * Returns the root of this tree. + * The root is defined to be the vertex (designated either at the tree's + * creation time, or as the first vertex to be added) with respect to which + * vertex depth is measured. + * @return the root of this tree + */ + public V getRoot(); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/UndirectedGraph.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/UndirectedGraph.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/UndirectedGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/UndirectedGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,18 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +/** + * A tagging interface for extensions of Graph that + * accept only undirected edges. + */ +public interface UndirectedGraph extends Graph {} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Context.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Context.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Context.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Context.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,50 @@ +package edu.uci.ics.jung.graph.util; + +/** + * A class that is used to link together a graph element and a specific graph. + * Provides appropriate implementations of hashCode and equals. + */ +public class Context +{ + @SuppressWarnings("rawtypes") + private static Context instance = new Context(); + + /** + * The graph element which defines this context. + */ + public G graph; + + /** + * The edge element which defines this context. + */ + public E element; + + /** + * @param the graph type + * @param the element type + * @param graph the graph for which the instance is created + * @param element the element for which the instance is created + * @return an instance of this type for the specified graph and element + */ + @SuppressWarnings("unchecked") + public static Context getInstance(G graph, E element) { + instance.graph = graph; + instance.element = element; + return instance; + } + + @Override + public int hashCode() { + return graph.hashCode() ^ element.hashCode(); + } + + @SuppressWarnings("rawtypes") + @Override + public boolean equals(Object o) { + if (!(o instanceof Context)) + return false; + Context context = (Context) o; + return context.graph.equals(graph) && context.element.equals(element); + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/DefaultParallelEdgeIndexFunction.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/DefaultParallelEdgeIndexFunction.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/DefaultParallelEdgeIndexFunction.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/DefaultParallelEdgeIndexFunction.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,148 @@ +/* + * Created on Sep 24, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph.util; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A class which creates and maintains indices for parallel edges. + * Parallel edges are defined here to be the collection of edges + * that are returned by v.findEdgeSet(w) for some + * v and w. + * + *

    At this time, users are responsible for resetting the indices + * (by calling reset()) if changes to the + * graph make it appropriate. + * + * @author Joshua O'Madadhain + * @author Tom Nelson + * + */ +public class DefaultParallelEdgeIndexFunction implements EdgeIndexFunction +{ + protected Map,E>, Integer> edge_index = new HashMap,E>, Integer>(); + + private DefaultParallelEdgeIndexFunction() { + } + + /** + * @param the vertex type + * @param the edge type + * @return an instance of this class + */ + public static DefaultParallelEdgeIndexFunction getInstance() { + return new DefaultParallelEdgeIndexFunction(); + } + + /** + * Returns the index for e in graph. + * Calculates the indices for e and for all edges parallel + * to e, if they are not already assigned. + */ + public int getIndex(Graph graph, E e) + { + checkNotNull(graph, "graph must not be null"); + checkNotNull(e, "'e' must not be null"); + Integer index = edge_index.get(Context.,E>getInstance(graph,e)); + //edge_index.get(e); + if(index == null) { + Pair endpoints = graph.getEndpoints(e); + V u = endpoints.getFirst(); + V v = endpoints.getSecond(); + if(u.equals(v)) { + index = getIndex(graph, e, v); + } else { + index = getIndex(graph, e, u, v); + } + } + return index.intValue(); + } + + protected int getIndex(Graph graph, E e, V v, V u) { + Collection commonEdgeSet = new HashSet(graph.getIncidentEdges(u)); + commonEdgeSet.retainAll(graph.getIncidentEdges(v)); + for(Iterator iterator=commonEdgeSet.iterator(); iterator.hasNext(); ) { + E edge = iterator.next(); + Pair ep = graph.getEndpoints(edge); + V first = ep.getFirst(); + V second = ep.getSecond(); + // remove loops + if(first.equals(second) == true) { + iterator.remove(); + } + // remove edges in opposite direction + if(first.equals(v) == false) { + iterator.remove(); + } + } + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(Context.,E>getInstance(graph,other), count); + count++; + } + } + edge_index.put(Context.,E>getInstance(graph,e), count); + return count; + } + + protected int getIndex(Graph graph, E e, V v) { + Collection commonEdgeSet = new HashSet(); + for(E another : graph.getIncidentEdges(v)) { + V u = graph.getOpposite(v, another); + if(u.equals(v)) { + commonEdgeSet.add(another); + } + } + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(Context.,E>getInstance(graph,other), count); + count++; + } + } + edge_index.put(Context.,E>getInstance(graph,e), count); + return count; + } + + + /** + * Resets the indices for this edge and its parallel edges. + * Should be invoked when an edge parallel to e + * has been added or removed. + * @param graph the graph for which the indices are to be reset + * @param e the edge whose indices are to be reset + * + */ + public void reset(Graph graph, E e) { + Pair endpoints = graph.getEndpoints(e); + getIndex(graph, e, endpoints.getFirst()); + getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond()); + } + + /** + * Clears all edge indices for all edges in all graphs. + * Does not recalculate the indices. + */ + public void reset() + { + edge_index.clear(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeIndexFunction.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeIndexFunction.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeIndexFunction.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeIndexFunction.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Created on Sep 24, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph.util; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * An interface for a service to access the index of a given edge (in a given graph) + * into the set formed by the given edge and all the other edges it is parallel to. + * + *

    Note that in current use, this index is assumed to be an integer value in + * the interval [0,n-1], where n-1 is the number of edges parallel to e. + * + * @author Tom Nelson + * + */ +public interface EdgeIndexFunction { + + /** + * Returns e's index in graph. + * The index of e is defined as its position in some + * consistent ordering of e and all edges parallel to e. + * @param graph the graph with respect to which the index is calculated + * @param e the edge whose index is to be queried + * @return e's index in graph + */ + int getIndex(Graph graph, E e); + + /** + * Resets the indices for edge and its parallel edges in graph. + * Should be invoked when an edge parallel to edge + * has been added or removed. + * + * @param g the graph in which edge's index is to be reset + * @param edge the edge whose index is to be reset + */ + void reset(Graph g, E edge); + + /** + * Clears all edge indices for all edges in all graphs. + * Does not recalculate the indices. + */ + void reset(); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeType.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeType.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeType.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/EdgeType.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,22 @@ +/* + * Created on February 27, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.graph.util; + +/** + * Defines the possible edge types for graphs which assign types to edges. + */ +public enum EdgeType +{ + DIRECTED, + UNDIRECTED +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Graphs.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Graphs.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Graphs.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Graphs.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,989 @@ +package edu.uci.ics.jung.graph.util; + +import java.io.Serializable; +import java.util.Collection; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.graph.UndirectedGraph; +/** + * Provides specialized implementations of GraphDecorator. Currently these + * wrapper types include "synchronized" and "unmodifiable". + * + *

    The methods of this class may each throw a NullPointerException + * if the graphs or class objects provided to them are null. + * + * @author Tom Nelson + */ + +public class Graphs { + + /** + * Returns a synchronized graph backed by the passed argument graph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which a synchronized wrapper is to be created + * @return a synchronized graph backed by the passed argument graph + */ + public static Graph synchronizedGraph(Graph graph) { + return new SynchronizedGraph(graph); + } + + /** + * Returns a synchronized DirectedGraph backed by the passed DirectedGraph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which a synchronized wrapper is to be created + * @return a synchronized DirectedGraph backed by the passed DirectedGraph + */ + public static DirectedGraph synchronizedDirectedGraph(DirectedGraph graph) { + return new SynchronizedDirectedGraph(graph); + } + + /** + * Returns a synchronized UndirectedGraph backed by the passed UndirectedGraph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which a synchronized wrapper is to be created + * @return a synchronized UndirectedGraph backed by the passed UndirectedGraph + */ + public static UndirectedGraph synchronizedUndirectedGraph(UndirectedGraph graph) { + return new SynchronizedUndirectedGraph(graph); + } + + /** + * Returns a synchronized Forest backed by the passed Forest. + * @param the vertex type + * @param the edge type + * @param forest the forest for which a synchronized wrapper is to be created + * @return a synchronized Forest backed by the passed Forest + */ + public static SynchronizedForest synchronizedForest(Forest forest) { + return new SynchronizedForest(forest); + } + + /** + * Returns a synchronized Tree backed by the passed Tree. + * @param the vertex type + * @param the edge type + * @param tree the tree for which a synchronized wrapper is to be created + * @return a synchronized Tree backed by the passed Tree + */ + public static SynchronizedTree synchronizedTree(Tree tree) { + return new SynchronizedTree(tree); + } + + /** + * Returns an unmodifiable Graph backed by the passed Graph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which the unmodifiable wrapper is to be returned + * @return an unmodifiable Graph backed by the passed Graph + */ + public static Graph unmodifiableGraph(Graph graph) { + return new UnmodifiableGraph(graph); + } + + /** + * Returns an unmodifiable DirectedGraph backed by the passed graph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which the unmodifiable wrapper is to be returned + * @return an unmodifiable DirectedGraph backed by the passed graph + */ + public static DirectedGraph unmodifiableDirectedGraph(DirectedGraph graph) { + return new UnmodifiableDirectedGraph(graph); + } + + /** + * Returns an unmodifiable UndirectedGraph backed by the passed graph. + * @param the vertex type + * @param the edge type + * @param graph the graph for which the unmodifiable wrapper is to be returned + * @return an unmodifiable UndirectedGraph backed by the passed graph + */ + public static UndirectedGraph unmodifiableUndirectedGraph(UndirectedGraph graph) { + return new UnmodifiableUndirectedGraph(graph); + } + + /** + * Returns an unmodifiable Tree backed by the passed tree. + * @param the vertex type + * @param the edge type + * @param tree the tree for which the unmodifiable wrapper is to be returned + * @return an unmodifiable Tree backed by the passed tree + */ + public static UnmodifiableTree unmodifiableTree(Tree tree) { + return new UnmodifiableTree(tree); + } + + /** + * Returns an unmodifiable Forest backed by the passed forest. + * @param the vertex type + * @param the edge type + * @param forest the forest for which the unmodifiable wrapper is to be returned + * @return an unmodifiable Forest backed by the passed forest + */ + public static UnmodifiableForest unmodifiableForest(Forest forest) { + return new UnmodifiableForest(forest); + } + + + @SuppressWarnings("serial") + static abstract class SynchronizedAbstractGraph implements Graph, Serializable { + protected Graph delegate; + + private SynchronizedAbstractGraph(Graph delegate) { + if(delegate == null) { + throw new NullPointerException(); + } + this.delegate = delegate; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDefaultEdgeType() + */ + public EdgeType getDefaultEdgeType() + { + return delegate.getDefaultEdgeType(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(Object, Object, Object, EdgeType) + */ + public synchronized boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + return delegate.addEdge(e, v1, v2, edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(Object, Collection, EdgeType) + */ + public synchronized boolean addEdge(E e, Collection + vertices, EdgeType edgeType) + { + return delegate.addEdge(e, vertices, edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(Object, Object, Object) + */ + public synchronized boolean addEdge(E e, V v1, V v2) { + return delegate.addEdge(e, v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object) + */ + public synchronized boolean addVertex(V vertex) { + return delegate.addVertex(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isIncident(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isIncident(V vertex, E edge) { + return delegate.isIncident(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isNeighbor(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isNeighbor(V v1, V v2) { + return delegate.isNeighbor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#degree(java.lang.Object) + */ + public synchronized int degree(V vertex) { + return delegate.degree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdge(java.lang.Object, java.lang.Object) + */ + public synchronized E findEdge(V v1, V v2) { + return delegate.findEdge(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdgeSet(java.lang.Object, java.lang.Object) + */ + public synchronized Collection findEdgeSet(V v1, V v2) + { + return delegate.findEdgeSet(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdges() + */ + public synchronized Collection getEdges() { + return delegate.getEdges(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdges(EdgeType) + */ + public synchronized Collection getEdges(EdgeType edgeType) { + return delegate.getEdges(edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEndpoints(java.lang.Object) + */ + public synchronized Pair getEndpoints(E edge) { + return delegate.getEndpoints(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentEdges(java.lang.Object) + */ + public synchronized Collection getIncidentEdges(V vertex) { + return delegate.getIncidentEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentVertices(java.lang.Object) + */ + public synchronized Collection getIncidentVertices(E edge) { + return delegate.getIncidentVertices(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getInEdges(java.lang.Object) + */ + public synchronized Collection getInEdges(V vertex) { + return delegate.getInEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighbors(java.lang.Object) + */ + public synchronized Collection getNeighbors(V vertex) { + return delegate.getNeighbors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOpposite(java.lang.Object, java.lang.Object) + */ + public synchronized V getOpposite(V vertex, E edge) { + return delegate.getOpposite(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOutEdges(java.lang.Object) + */ + public synchronized Collection getOutEdges(V vertex) { + return delegate.getOutEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessors(java.lang.Object) + */ + public synchronized Collection getPredecessors(V vertex) { + return delegate.getPredecessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessors(java.lang.Object) + */ + public synchronized Collection getSuccessors(V vertex) { + return delegate.getSuccessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertices() + */ + public synchronized Collection getVertices() { + return delegate.getVertices(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount() + */ + public synchronized int getEdgeCount() { + return delegate.getEdgeCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount(EdgeType) + */ + public synchronized int getEdgeCount(EdgeType edge_type) + { + return delegate.getEdgeCount(edge_type); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertexCount() + */ + public synchronized int getVertexCount() { + return delegate.getVertexCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#inDegree(java.lang.Object) + */ + public synchronized int inDegree(V vertex) { + return delegate.inDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdgeType(java.lang.Object) + */ + public synchronized EdgeType getEdgeType(E edge) { + return delegate.getEdgeType(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isPredecessor(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isPredecessor(V v1, V v2) { + return delegate.isPredecessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSuccessor(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isSuccessor(V v1, V v2) { + return delegate.isSuccessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighborCount(java.lang.Object) + */ + public synchronized int getNeighborCount(V vertex) { + return delegate.getNeighborCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessorCount(java.lang.Object) + */ + public synchronized int getPredecessorCount(V vertex) { + return delegate.getPredecessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessorCount(java.lang.Object) + */ + public synchronized int getSuccessorCount(V vertex) { + return delegate.getSuccessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#outDegree(java.lang.Object) + */ + public synchronized int outDegree(V vertex) { + return delegate.outDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + public synchronized boolean removeEdge(E edge) { + return delegate.removeEdge(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + public synchronized boolean removeVertex(V vertex) { + return delegate.removeVertex(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDest(java.lang.Object) + */ + public synchronized V getDest(E directed_edge) { + return delegate.getDest(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSource(java.lang.Object) + */ + public synchronized V getSource(E directed_edge) { + return delegate.getSource(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isDest(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isDest(V vertex, E edge) { + return delegate.isDest(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSource(java.lang.Object, java.lang.Object) + */ + public synchronized boolean isSource(V vertex, E edge) { + return delegate.isSource(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentCount(Object) + */ + public synchronized int getIncidentCount(E edge) + { + return delegate.getIncidentCount(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection) + */ + public synchronized boolean addEdge(E hyperedge, Collection vertices) { + return delegate.addEdge(hyperedge, vertices); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsEdge(java.lang.Object) + */ + public synchronized boolean containsEdge(E edge) { + return delegate.containsEdge(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsVertex(java.lang.Object) + */ + public synchronized boolean containsVertex(V vertex) { + return delegate.containsVertex(vertex); + } + + } + + @SuppressWarnings("serial") + static class SynchronizedGraph extends SynchronizedAbstractGraph implements Serializable { + + private SynchronizedGraph(Graph delegate) { + super(delegate); + } + } + + @SuppressWarnings("serial") + static class SynchronizedUndirectedGraph extends SynchronizedAbstractGraph + implements UndirectedGraph, Serializable { + private SynchronizedUndirectedGraph(UndirectedGraph delegate) { + super(delegate); + } + } + + @SuppressWarnings("serial") + static class SynchronizedDirectedGraph extends SynchronizedAbstractGraph + implements DirectedGraph, Serializable { + + private SynchronizedDirectedGraph(DirectedGraph delegate) { + super(delegate); + } + + @Override + public synchronized V getDest(E directed_edge) { + return ((DirectedGraph)delegate).getDest(directed_edge); + } + + @Override + public synchronized V getSource(E directed_edge) { + return ((DirectedGraph)delegate).getSource(directed_edge); + } + + @Override + public synchronized boolean isDest(V vertex, E edge) { + return ((DirectedGraph)delegate).isDest(vertex, edge); + } + + @Override + public synchronized boolean isSource(V vertex, E edge) { + return ((DirectedGraph)delegate).isSource(vertex, edge); + } + } + + @SuppressWarnings("serial") + static class SynchronizedTree extends SynchronizedForest implements Tree { + + /** + * Creates a new instance based on the provided {@code delegate}. + * @param delegate + */ + public SynchronizedTree(Tree delegate) { + super(delegate); + } + + public synchronized int getDepth(V vertex) { + return ((Tree)delegate).getDepth(vertex); + } + + public synchronized int getHeight() { + return ((Tree)delegate).getHeight(); + } + + public synchronized V getRoot() { + return ((Tree)delegate).getRoot(); + } + } + + @SuppressWarnings("serial") + static class SynchronizedForest extends SynchronizedDirectedGraph implements Forest { + + /** + * Creates a new instance based on the provided {@code delegate}. + * @param delegate + */ + public SynchronizedForest(Forest delegate) { + super(delegate); + } + + public synchronized Collection> getTrees() { + return ((Forest)delegate).getTrees(); + } + + public int getChildCount(V vertex) + { + return ((Forest)delegate).getChildCount(vertex); + } + + public Collection getChildEdges(V vertex) + { + return ((Forest)delegate).getChildEdges(vertex); + } + + public Collection getChildren(V vertex) + { + return ((Forest)delegate).getChildren(vertex); + } + + public V getParent(V vertex) + { + return ((Forest)delegate).getParent(vertex); + } + + public E getParentEdge(V vertex) + { + return ((Forest)delegate).getParentEdge(vertex); + } + } + + @SuppressWarnings("serial") + static abstract class UnmodifiableAbstractGraph implements Graph, Serializable { + protected Graph delegate; + + + private UnmodifiableAbstractGraph(Graph delegate) { + if(delegate == null) { + throw new NullPointerException(); + } + this.delegate = delegate; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDefaultEdgeType() + */ + public EdgeType getDefaultEdgeType() + { + return delegate.getDefaultEdgeType(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(Object, Object, Object, EdgeType) + */ + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(Object, Collection, EdgeType) + */ + public boolean addEdge(E e, Collection vertices, + EdgeType edgeType) + { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(Object, Object, Object) + */ + public boolean addEdge(E e, V v1, V v2) { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object) + */ + public boolean addVertex(V vertex) { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isIncident(java.lang.Object, java.lang.Object) + */ + public boolean isIncident(V vertex, E edge) { + return delegate.isIncident(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isNeighbor(java.lang.Object, java.lang.Object) + */ + public boolean isNeighbor(V v1, V v2) { + return delegate.isNeighbor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#degree(java.lang.Object) + */ + public int degree(V vertex) { + return delegate.degree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdge(java.lang.Object, java.lang.Object) + */ + public E findEdge(V v1, V v2) { + return delegate.findEdge(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdgeSet(java.lang.Object, java.lang.Object) + */ + public Collection findEdgeSet(V v1, V v2) + { + return delegate.findEdgeSet(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdges() + */ + public Collection getEdges() { + return delegate.getEdges(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount() + */ + public int getEdgeCount() { + return delegate.getEdgeCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount(EdgeType) + */ + public int getEdgeCount(EdgeType edge_type) + { + return delegate.getEdgeCount(edge_type); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertexCount() + */ + public int getVertexCount() { + return delegate.getVertexCount(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdges(edu.uci.ics.jung.graph.util.EdgeType) + */ + public Collection getEdges(EdgeType edgeType) { + return delegate.getEdges(edgeType); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEndpoints(java.lang.Object) + */ + public Pair getEndpoints(E edge) { + return delegate.getEndpoints(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentEdges(java.lang.Object) + */ + public Collection getIncidentEdges(V vertex) { + return delegate.getIncidentEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentVertices(java.lang.Object) + */ + public Collection getIncidentVertices(E edge) { + return delegate.getIncidentVertices(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getInEdges(java.lang.Object) + */ + public Collection getInEdges(V vertex) { + return delegate.getInEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighbors(java.lang.Object) + */ + public Collection getNeighbors(V vertex) { + return delegate.getNeighbors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOpposite(java.lang.Object, java.lang.Object) + */ + public V getOpposite(V vertex, E edge) { + return delegate.getOpposite(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOutEdges(java.lang.Object) + */ + public Collection getOutEdges(V vertex) { + return delegate.getOutEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessors(java.lang.Object) + */ + public Collection getPredecessors(V vertex) { + return delegate.getPredecessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessors(java.lang.Object) + */ + public Collection getSuccessors(V vertex) { + return delegate.getSuccessors(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertices() + */ + public Collection getVertices() { + return delegate.getVertices(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#inDegree(java.lang.Object) + */ + public int inDegree(V vertex) { + return delegate.inDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEdgeType(java.lang.Object) + */ + public EdgeType getEdgeType(E edge) { + return delegate.getEdgeType(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isPredecessor(java.lang.Object, java.lang.Object) + */ + public boolean isPredecessor(V v1, V v2) { + return delegate.isPredecessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSuccessor(java.lang.Object, java.lang.Object) + */ + public boolean isSuccessor(V v1, V v2) { + return delegate.isSuccessor(v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighborCount(java.lang.Object) + */ + public int getNeighborCount(V vertex) { + return delegate.getNeighborCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessorCount(java.lang.Object) + */ + public int getPredecessorCount(V vertex) { + return delegate.getPredecessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessorCount(java.lang.Object) + */ + public int getSuccessorCount(V vertex) { + return delegate.getSuccessorCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#outDegree(java.lang.Object) + */ + public int outDegree(V vertex) { + return delegate.outDegree(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + public boolean removeEdge(E edge) { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + public boolean removeVertex(V vertex) { + throw new UnsupportedOperationException(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDest(java.lang.Object) + */ + public V getDest(E directed_edge) { + return delegate.getDest(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSource(java.lang.Object) + */ + public V getSource(E directed_edge) { + return delegate.getSource(directed_edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isDest(java.lang.Object, java.lang.Object) + */ + public boolean isDest(V vertex, E edge) { + return delegate.isDest(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSource(java.lang.Object, java.lang.Object) + */ + public boolean isSource(V vertex, E edge) { + return delegate.isSource(vertex, edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentCount(Object) + */ + public int getIncidentCount(E edge) + { + return delegate.getIncidentCount(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection) + */ + public boolean addEdge(E hyperedge, Collection vertices) { + return delegate.addEdge(hyperedge, vertices); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsEdge(java.lang.Object) + */ + public boolean containsEdge(E edge) { + return delegate.containsEdge(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsVertex(java.lang.Object) + */ + public boolean containsVertex(V vertex) { + return delegate.containsVertex(vertex); + } + } + + @SuppressWarnings("serial") + static class UnmodifiableGraph extends UnmodifiableAbstractGraph implements Serializable { + private UnmodifiableGraph(Graph delegate) { + super(delegate); + } + } + + @SuppressWarnings("serial") + static class UnmodifiableDirectedGraph extends UnmodifiableAbstractGraph + implements DirectedGraph, Serializable { + private UnmodifiableDirectedGraph(DirectedGraph delegate) { + super(delegate); + } + + @Override + public V getDest(E directed_edge) { + return ((DirectedGraph)delegate).getDest(directed_edge); + } + + @Override + public V getSource(E directed_edge) { + return ((DirectedGraph)delegate).getSource(directed_edge); + } + + @Override + public boolean isDest(V vertex, E edge) { + return ((DirectedGraph)delegate).isDest(vertex, edge); + } + + @Override + public boolean isSource(V vertex, E edge) { + return ((DirectedGraph)delegate).isSource(vertex, edge); + } + } + + @SuppressWarnings("serial") + static class UnmodifiableUndirectedGraph extends UnmodifiableAbstractGraph + implements UndirectedGraph, Serializable { + private UnmodifiableUndirectedGraph(UndirectedGraph delegate) { + super(delegate); + } + } + + @SuppressWarnings("serial") + static class UnmodifiableForest extends UnmodifiableGraph + implements Forest, Serializable { + private UnmodifiableForest(Forest delegate) { + super(delegate); + } + + public Collection> getTrees() { + return ((Forest)delegate).getTrees(); + } + + public int getChildCount(V vertex) + { + return ((Forest)delegate).getChildCount(vertex); + } + + public Collection getChildEdges(V vertex) + { + return ((Forest)delegate).getChildEdges(vertex); + } + + public Collection getChildren(V vertex) + { + return ((Forest)delegate).getChildren(vertex); + } + + public V getParent(V vertex) + { + return ((Forest)delegate).getParent(vertex); + } + + public E getParentEdge(V vertex) + { + return ((Forest)delegate).getParentEdge(vertex); + } + } + + @SuppressWarnings("serial") + static class UnmodifiableTree extends UnmodifiableForest + implements Tree, Serializable { + private UnmodifiableTree(Tree delegate) { + super(delegate); + } + + public int getDepth(V vertex) { + return ((Tree)delegate).getDepth(vertex); + } + + public int getHeight() { + return ((Tree)delegate).getHeight(); + } + + public V getRoot() { + return ((Tree)delegate).getRoot(); + } + + @Override + public Collection> getTrees() { + return ((Tree)delegate).getTrees(); + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/IncidentEdgeIndexFunction.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/IncidentEdgeIndexFunction.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/IncidentEdgeIndexFunction.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/IncidentEdgeIndexFunction.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,118 @@ +/* + * Created on Sep 24, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import edu.uci.ics.jung.graph.Graph; + +/** + * A class which creates and maintains indices for incident edges. + * + * @author Tom Nelson + * + */ +public class IncidentEdgeIndexFunction implements EdgeIndexFunction +{ + protected Map edge_index = new HashMap(); + + private IncidentEdgeIndexFunction() { + } + + /** + * @param the vertex type + * @param the edge type + * @return an instance of this type. + */ + public static IncidentEdgeIndexFunction getInstance() { + return new IncidentEdgeIndexFunction(); + } + + /** + * Returns the index for the specified edge. + * Calculates the indices for e and for all edges parallel + * to e. + */ + public int getIndex(Graph graph, E e) + { + Integer index = edge_index.get(e); + if(index == null) { + Pair endpoints = graph.getEndpoints(e); + V u = endpoints.getFirst(); + V v = endpoints.getSecond(); + if(u.equals(v)) { + index = getIndex(graph, e, v); + } else { + index = getIndex(graph, e, u, v); + } + } + return index.intValue(); + } + + protected int getIndex(Graph graph, E e, V u, V v) { + Collection commonEdgeSet = new HashSet(graph.getIncidentEdges(u)); + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(other, count); + count++; + } + } + edge_index.put(e, count); + return count; + } + + protected int getIndex(Graph graph, E e, V v) { + Collection commonEdgeSet = new HashSet(); + for(E another : graph.getIncidentEdges(v)) { + V u = graph.getOpposite(v, another); + if(u.equals(v)) { + commonEdgeSet.add(another); + } + } + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(other, count); + count++; + } + } + edge_index.put(e, count); + return count; + } + + + /** + * Resets the indices for this edge and its parallel edges. + * Should be invoked when an edge parallel to e + * has been added or removed. + * @param graph the graph whose indices are to be reset + * @param e the edge whose associated indices are to be reset + */ + public void reset(Graph graph, E e) { + Pair endpoints = graph.getEndpoints(e); + getIndex(graph, e, endpoints.getFirst()); + getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond()); + } + + /** + * Clears all edge indices for all edges in all graphs. + * Does not recalculate the indices. + */ + public void reset() + { + edge_index.clear(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/package.html libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/package.html --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ + + + + + + + +

    Utility interfaces and classes for the JUNG API. These include: + +

      +
    • Context: a wrapper for an element in the context of a specific graph +
    • classes for maintaining edge indices (primarily for rendering) +
    • Pair<T>: an implementation of Collection designed for +two-element immutable collections +
    • Graphs: facilitates the creation of special delegate +types such as synchronized and unmodifiable graphs +
    • TreeUtils: utilities for trees and forests (subtree extraction, grafting, merging, etc.) +
    + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Pair.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Pair.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Pair.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/Pair.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * Created on Apr 2, 2006 + * + * Copyright (c) 2006, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph.util; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Iterator; + + +/** + * An implementation of Collection that stores exactly + * 2 non-null objects and is not mutable. They respect equals + * and may be used as indices or map keys.

    + * Note that they do not protect from malevolent behavior: if one or another + * object in the tuple is mutable, then it can be changed with the usual bad + * effects. + */ +@SuppressWarnings("serial") +public final class Pair implements Collection, Serializable +{ + private T first; + private T second; + + /** + * Creates a Pair from the specified elements. + * @param value1 the first value in the new Pair + * @param value2 the second value in the new Pair + * @throws IllegalArgumentException if either argument is null + */ + public Pair(T value1, T value2) + { + if(value1 == null || value2 == null) + throw new IllegalArgumentException("Pair cannot contain null values"); + first = value1; + second = value2; + } + + /** + * Creates a Pair from the passed Collection. + * The size of the Collection must be 2. + * @param values the elements of the new Pair + * @throws IllegalArgumentException if the input collection is null, + * contains null values, or has != 2 elements. + */ + public Pair(Collection values) + { + if (values == null) + throw new IllegalArgumentException("Input collection cannot be null"); + if (values.size() == 2) + { + if(values.contains(null)) + throw new IllegalArgumentException("Pair cannot contain null values"); + Iterator iter = values.iterator(); + first = iter.next(); + second = iter.next(); + } + else + throw new IllegalArgumentException("Pair may only be created from a Collection of exactly 2 elements"); + + } + + /** + * Creates a Pair from the passed array. + * The size of the array must be 2. + * + * @param values the values to be used to construct this Pair + * @throws IllegalArgumentException if the input array is null, + * contains null values, or has != 2 elements. + */ + public Pair(T[] values) + { + if (values == null) + throw new IllegalArgumentException("Input array cannot be null"); + if (values.length == 2) + { + if(values[0] == null || values[1] == null) + throw new IllegalArgumentException("Pair cannot contain null values"); + first = values[0]; + second = values[1]; + } + else + throw new IllegalArgumentException("Pair may only be created from an " + + "array of 2 elements"); + } + + /** + * @return the first element. + */ + public T getFirst() + { + return first; + } + + /** + * @return the second element. + */ + public T getSecond() + { + return second; + } + + @Override + public boolean equals( Object o ) { + if (o == this) + return true; + + if (o instanceof Pair) { + @SuppressWarnings("rawtypes") + Pair otherPair = (Pair) o; + Object otherFirst = otherPair.getFirst(); + Object otherSecond = otherPair.getSecond(); + return + (this.first == otherFirst || + (this.first != null && this.first.equals(otherFirst))) + && + (this.second == otherSecond || + (this.second != null && this.second.equals(otherSecond))); + } else { + return false; + } + } + + @Override + public int hashCode() + { + int hashCode = 1; + hashCode = 31*hashCode + (first==null ? 0 : first.hashCode()); + hashCode = 31*hashCode + (second==null ? 0 : second.hashCode()); + return hashCode; + } + + @Override + public String toString() + { + return "<" + first.toString() + ", " + second.toString() + ">"; + } + + public boolean add(T o) { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public boolean addAll(Collection c) { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public void clear() { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public boolean contains(Object o) { + return (first == o || first.equals(o) || second == o || second.equals(o)); + } + + public boolean containsAll(Collection c) { + if (c.size() > 2) + return false; + Iterator iter = c.iterator(); + Object c_first = iter.next(); + Object c_second = iter.next(); + return this.contains(c_first) && this.contains(c_second); + } + + public boolean isEmpty() { + return false; + } + + public Iterator iterator() { + return new PairIterator(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + + public int size() { + return 2; + } + + public Object[] toArray() { + Object[] to_return = new Object[2]; + to_return[0] = first; + to_return[1] = second; + return to_return; + } + + @SuppressWarnings("unchecked") + public S[] toArray(S[] a) { + S[] to_return = a; + Class type = a.getClass().getComponentType(); + if (a.length < 2) + to_return = (S[])java.lang.reflect.Array.newInstance(type, 2); + to_return[0] = (S)first; + to_return[1] = (S)second; + + if (to_return.length > 2) + to_return[2] = null; + return to_return; + } + + private class PairIterator implements Iterator + { + int position; + + private PairIterator() + { + position = 0; + } + + public boolean hasNext() + { + return position < 2; + } + + public T next() + { + position++; + if (position == 1) + return first; + else if (position == 2) + return second; + else + return null; + } + + public void remove() + { + throw new UnsupportedOperationException("Pairs cannot be mutated"); + } + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/TreeUtils.java libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/TreeUtils.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/main/java/edu/uci/ics/jung/graph/util/TreeUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/main/java/edu/uci/ics/jung/graph/util/TreeUtils.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Created on Mar 3, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph.util; + +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Tree; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Contains static methods for operating on instances of Tree. + */ +public class TreeUtils +{ + /** + * @param the vertex type + * @param the edge type + * @param forest the forest whose roots are to be returned + * @return the roots of this forest. + */ + public static List getRoots(Forest forest) + { + List roots = new ArrayList(); + for(Tree tree : forest.getTrees()) { + roots.add(tree.getRoot()); + } + return roots; + } + + /** + * Returns the subtree of tree which is rooted at root as a Forest. + * The tree returned is an independent entity, although it uses the same vertex and edge objects. + * @param the vertex type + * @param the edge type + * @param forest the tree whose subtree is to be extracted + * @param root the root of the subtree to be extracted + * @return the subtree of tree which is rooted at root + * @throws InstantiationException if a new tree of the same type cannot be created + * @throws IllegalAccessException if a new tree of the same type cannot be created + */ + @SuppressWarnings("unchecked") + public static Tree getSubTree(Forest forest, V root) throws InstantiationException, IllegalAccessException + { + if (!forest.containsVertex(root)) + throw new IllegalArgumentException("Specified tree does not contain the specified root as a vertex"); + Forest subforest = forest.getClass().newInstance(); + subforest.addVertex(root); + growSubTree(forest, subforest, root); + + return subforest.getTrees().iterator().next(); + } + + /** + * Populates subtree with the subtree of tree + * which is rooted at root. + * @param the vertex type + * @param the edge type + * @param tree the tree whose subtree is to be extracted + * @param subTree the tree instance which is to be populated with the subtree of tree + * @param root the root of the subtree to be extracted + */ + public static void growSubTree(Forest tree, Forest subTree, V root) { + if(tree.getSuccessorCount(root) > 0) { + Collection edges = tree.getOutEdges(root); + for(E e : edges) { + subTree.addEdge(e, tree.getEndpoints(e)); + } + Collection kids = tree.getSuccessors(root); + for(V kid : kids) { + growSubTree(tree, subTree, kid); + } + } + } + + /** + * Connects subTree to tree by attaching it as a child + * of node with edge connectingEdge. + * @param the vertex type + * @param the edge type + * @param tree the tree to which subTree is to be added + * @param subTree the tree which is to be grafted on to tree + * @param node the parent of subTree in its new position in tree + * @param connectingEdge the edge used to connect subtree's root as a child of node + */ + public static void addSubTree(Forest tree, Forest subTree, + V node, E connectingEdge) { + if (node != null && !tree.containsVertex(node)) + throw new IllegalArgumentException("Specified tree does not contain the specified node as a vertex"); + V root = subTree.getTrees().iterator().next().getRoot(); + addFromSubTree(tree, subTree, connectingEdge, node, root); + } + + public static void addFromSubTree(Forest tree, Forest subTree, + E edge, V parent, V root) { + + // add edge connecting parent and root to tree + if(edge != null && parent != null) { + tree.addEdge(edge, parent, root); + } else { + tree.addVertex(root); + } + + Collection outEdges = subTree.getOutEdges(root); + for(E e : outEdges) { + V opposite = subTree.getOpposite(root, e); + addFromSubTree(tree, subTree, e, root, opposite); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/site/site.xml libjung-free-java-2.1.1/jung-api/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-api/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + +

    + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractDirectedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractDirectedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractDirectedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractDirectedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,131 @@ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; + +import junit.framework.TestCase; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public abstract class AbstractDirectedSparseMultigraphTest extends TestCase { + + protected Integer v0 = new Integer(0); + protected Integer v1 = new Integer(1); + protected Integer v2 = new Integer(2); + + protected Float e01 = new Float(.1f); + protected Float e10 = new Float(.2f); + protected Float e12 = new Float(.3f); + protected Float e21 = new Float(.4f); + + protected Graph graph; + + public void testGetEdges() { + assertEquals(graph.getEdgeCount(), 4); + } + + public void testGetVertices() { + assertEquals(graph.getVertexCount(), 3); + } + + public void testAddVertex() { + int count = graph.getVertexCount(); + graph.addVertex(new Integer(3)); + assertEquals(graph.getVertexCount(), count+1); + } + + public void testRemoveEndVertex() { + int vertexCount = graph.getVertexCount(); + graph.removeVertex(v0); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(2, graph.getEdgeCount()); + } + + public void testRemoveMiddleVertex() { + int vertexCount = graph.getVertexCount(); + graph.removeVertex(v1); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(0, graph.getEdgeCount()); + } + + public void testAddEdge() { + int edgeCount = graph.getEdgeCount(); + graph.addEdge(new Double(.5), v0, v1); + assertEquals(graph.getEdgeCount(), edgeCount+1); + } + + public void testRemoveEdge() { + int edgeCount = graph.getEdgeCount(); + graph.removeEdge(e12); + assertEquals(graph.getEdgeCount(), edgeCount-1); + } + + public void testNullEndpoint() { + try { + graph.addEdge(.99, new Pair(1,null)); + fail("should not be able to add an edge with a null endpoint"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + public void testGetInEdges() { + assertEquals(graph.getInEdges(v1).size(), 2); + } + + public void testGetOutEdges() { + assertEquals(graph.getOutEdges(v1).size(), 2); + } + + public void testGetPredecessors() { + assertTrue(graph.getPredecessors(v0).containsAll(Collections.singleton(v1))); + } + + public void testGetSuccessors() { + assertTrue(graph.getPredecessors(v1).contains(v0)); + assertTrue(graph.getPredecessors(v1).contains(v2)); + } + + public void testGetNeighbors() { + Collection neighbors = graph.getNeighbors(v1); + assertTrue(neighbors.contains(v0)); + assertTrue(neighbors.contains(v2)); + } + + public void testGetIncidentEdges() { + assertEquals(graph.getIncidentEdges(v0).size(), 2); + } + + public void testFindEdge() { + Number edge = graph.findEdge(v1, v2); + assertTrue(edge == e12 || edge == e21); + } + + public void testGetEndpoints() { + Pair endpoints = graph.getEndpoints(e01); + assertTrue((endpoints.getFirst() == v0 && endpoints.getSecond() == v1) || + endpoints.getFirst() == v1 && endpoints.getSecond() == v0); + } + + public void testIsDirected() { + for(Number edge : graph.getEdges()) { + assertEquals(graph.getEdgeType(edge), EdgeType.DIRECTED); + } + } + + public void testAddDirectedEdge() { + Float edge = new Float(.9); + graph.addEdge(edge, v1, v2, EdgeType.DIRECTED); + assertEquals(graph.getEdgeType(edge), EdgeType.DIRECTED); + } + + public void testAddUndirectedEdge() { + try { + graph.addEdge(new Float(.9), v1, v2, EdgeType.UNDIRECTED); + fail("Cannot add an undirected edge to this graph"); + } catch(IllegalArgumentException uoe) { + // all is well + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractHypergraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractHypergraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractHypergraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractHypergraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,172 @@ +/* + * Created on Apr 21, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; + +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.Pair; + + +public abstract class AbstractHypergraphTest extends TestCase +{ + protected Supplier> factory; + protected Hypergraph h; + + public AbstractHypergraphTest(Supplier> factory) + { + this.factory = factory; + } + + @Override + public void runTest() throws Exception { + setUp(); + testAddVertex(); + testAddEdge(); + testEdgeEndpoints(); + tearDown(); + } + + /** + * test for the following: + *
      + *
    • add successful iff arg is not present + *
    • count increases by 1 iff add is successful + *
    • null vertex argument actively rejected + *
    • vertex reported as present iff add is successful + *
    + */ + public void testAddVertex() + { + int count = h.getVertexCount(); + assertTrue(h.addVertex(new Integer(1))); + assertEquals(count+1, h.getVertexCount()); + assertTrue(h.containsVertex(1)); + boolean success = false; + try + { + success = h.addVertex(null); + fail("Implementation should disallow null vertices"); + } + catch (IllegalArgumentException iae) {} + catch (NullPointerException npe) + { + fail("Implementation should actively prevent null vertices"); + } + assertFalse(success); + assertFalse(h.addVertex(1)); + assertEquals(count+1, h.getVertexCount()); + assertFalse(h.containsVertex(2)); + } + + /** + * test for the following: + *
      + *
    • add successful iff edge is not present + *
    • edge count increases by 1 iff add successful + *
    • null edge arg actively rejected + *
    • edge reported as present iff add is successful + *
    • throw if edge is present with different endpoints + *
    + */ + public void testAddEdge() + { + int edge_count = h.getEdgeCount(); + int vertex_count = h.getVertexCount(); + Pair p = new Pair(2, 3); + assertTrue(h.addEdge('a', p)); + assertEquals(edge_count+1, h.getEdgeCount()); + assertEquals(vertex_count+2, h.getVertexCount()); + assertTrue(h.containsEdge('a')); + boolean success = false; + try + { + success = h.addEdge('b', null); + fail("Implementation should disallow null pairs/collections"); + success = h.addEdge(null, p); + fail("Implementation should disallow null edges"); + } + catch (IllegalArgumentException iae) {} + catch (NullPointerException npe) + { + fail("Implementation should actively prevent null edges, pairs, and collections"); + } + assertFalse(success); + // adding the same edge with an equal Pair should return false + assertFalse(h.addEdge('a', new Pair(2,3))); + // adding the same edge with the same Pair should return false + assertFalse(h.addEdge('a', p)); + try + { + success = h.addEdge('a', new Pair(3,4)); + fail("Implementation should disallow existing edge objects from connecting new pairs/collections"); + } + catch (IllegalArgumentException iae) {} + assertEquals(edge_count+1, h.getEdgeCount()); + assertFalse(h.containsEdge('b')); + } + + /** + * test for the following: + *
      + *
    • if Graph, reject # of endpoints != 2 + *
    • otherwise, accept any (non-negative) number of endpoints + * + *
    + * + */ + public void testEdgeEndpoints() + { + Collection c = new ArrayList(); + for (int i = 0; i < 10; i++) + { + try + { + h.addEdge((char)i, c); + c.add(i); + } + catch (IllegalArgumentException iae) + { + if (h instanceof Graph) + { + if (c.size() == 2) + fail("improperly rejected incident vertex collection " + c); + } + else + fail("hypergraph implementations should accept any positive number of incident vertices"); + } + } + } + + /** + * should return null if any of the following is true + *
      + *
    • v1 is null + *
    • v2 is null + *
    • there is no edge connecting v1 to v2 in this graph + *
    + * otherwise should return _an_ edge connecting v1 to v2. + * May be directed or undirected (depending on the graph); + * may be any of the edges in the graph that so connect v1 and v2. + * + * Must _not_ return any directed edge for which v1 and v2 are distinct + * and v2 is the source. + */ + public void testFindEdge() + { + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractOrderedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractOrderedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractOrderedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractOrderedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,162 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public abstract class AbstractOrderedSparseMultigraphTest extends TestCase { + + protected Integer v0 = 0; + protected Integer v1 = 1; + protected Integer v2 = 2; + protected Number e01 = .1; + protected Number e10 = .2; + protected Number e12 = .3; + protected Number e21 = .4; + + protected Supplier vertexFactory = new Supplier() { + int v=0; + public Number get() { + return v++; + } + }; + protected Supplier edgeFactory = new Supplier() { + int e=0; + public Number get() { + return e++; + } + }; + + protected Graph graph; + protected int vertexCount = 50; + protected Graph smallGraph; + + public void testGetEdges() { + assertEquals(smallGraph.getEdgeCount(), 4); +// System.err.println("getEdges()="+graph.getEdges()); + } + + public void testGetVertices() { + assertEquals(smallGraph.getVertexCount(), 3); +// System.err.println("getVertices()="+graph.getVertices()); + } + + public void testAddVertex() { + int count = graph.getVertexCount(); + graph.addVertex(count); + assertEquals(graph.getVertexCount(), count+1); + } + + public void testRemoveEndVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount-1); + graph.removeVertex(vertexCount-1); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testRemoveMiddleVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount/2); + graph.removeVertex(vertexCount/2); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testAddEdge() { + int edgeCount = graph.getEdgeCount(); + graph.addEdge(edgeFactory.get(), 0, 1); + assertEquals(graph.getEdgeCount(), edgeCount+1); + } + + public void testNullEndpoint() { + try { + graph.addEdge(edgeFactory.get(), new Pair(1,null)); + fail("should not be able to add an edge with a null endpoint"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + + public void testRemoveEdge() { + List edgeList = new ArrayList(graph.getEdges()); + int edgeCount = graph.getEdgeCount(); + graph.removeEdge(edgeList.get(edgeList.size()/2)); + assertEquals(graph.getEdgeCount(), edgeCount-1); + } + + public void testGetInOutEdges() { + for(Number v : graph.getVertices()) { + Collection incident = graph.getIncidentEdges(v); + Collection in = graph.getInEdges(v); + Collection out = graph.getOutEdges(v); + assertTrue(incident.containsAll(in)); + assertTrue(incident.containsAll(out)); + for(Number e : in) { + if(out.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + for(Number e : out) { + if(in.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + } + + assertEquals(smallGraph.getInEdges(v1).size(), 4); + assertEquals(smallGraph.getOutEdges(v1).size(), 3); + assertEquals(smallGraph.getOutEdges(v0).size(), 2); + } + + public void testGetPredecessors() { + assertTrue(smallGraph.getPredecessors(v0).containsAll(Collections.singleton(v1))); + } + + public void testGetSuccessors() { + assertTrue(smallGraph.getPredecessors(v1).contains(v0)); + assertTrue(smallGraph.getPredecessors(v1).contains(v2)); + } + + public void testGetNeighbors() { + Collection neighbors = smallGraph.getNeighbors(v1); + assertTrue(neighbors.contains(v0)); + assertTrue(neighbors.contains(v2)); + } + + public void testGetIncidentEdges() { + assertEquals(smallGraph.getIncidentEdges(v0).size(), 2); + } + + public void testFindEdge() { + Number edge = smallGraph.findEdge(v1, v2); + assertTrue(edge == e12 || edge == e21); + } + + public void testGetEndpoints() { + Pair endpoints = smallGraph.getEndpoints(e01); + assertTrue((endpoints.getFirst() == v0 && endpoints.getSecond() == v1) || + endpoints.getFirst() == v1 && endpoints.getSecond() == v0); + } + + public void testIsDirected() { + for(Number edge : smallGraph.getEdges()) { + if(edge == e21) { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.DIRECTED); + } else { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.UNDIRECTED); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSortedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSortedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSortedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSortedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,164 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public abstract class AbstractSortedSparseMultigraphTest extends TestCase { + + public static class Foo {} + public static class Bar {} + protected Integer v0 = 0; + protected Integer v1 = 1; + protected Integer v2 = 2; + protected Double e01 = .1; + protected Double e10 = .2; + protected Double e12 = .3; + protected Double e21 = .4; + + protected Supplier vertexFactory = new Supplier() { + int v=0; + public Number get() { + return v++; + } + }; + protected Supplier edgeFactory = new Supplier() { + double e=0; + public Double get() { + return e++; + } + }; + + protected Graph graph; + protected int vertexCount = 50; + protected Graph smallGraph; + + public void testGetEdges() { + assertEquals(smallGraph.getEdgeCount(), 4); +// System.err.println("getEdges()="+graph.getEdges()); + } + + public void testGetVertices() { + assertEquals(smallGraph.getVertexCount(), 3); +// System.err.println("getVertices()="+graph.getVertices()); + } + + public void testAddVertex() { + int count = graph.getVertexCount(); + graph.addVertex(count); + assertEquals(graph.getVertexCount(), count+1); + } + + public void testRemoveEndVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount-1); + graph.removeVertex(vertexCount-1); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testRemoveMiddleVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount/2); + graph.removeVertex(vertexCount/2); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testAddEdge() { + int edgeCount = graph.getEdgeCount(); + graph.addEdge(edgeFactory.get(), 0, 1); + assertEquals(graph.getEdgeCount(), edgeCount+1); + } + + public void testNullEndpoint() { + try { + graph.addEdge(edgeFactory.get(), new Pair(1,null)); + fail("should not be able to add an edge with a null endpoint"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + + public void testRemoveEdge() { + List edgeList = new ArrayList(graph.getEdges()); + int edgeCount = graph.getEdgeCount(); + graph.removeEdge(edgeList.get(edgeList.size()/2)); + assertEquals(graph.getEdgeCount(), edgeCount-1); + } + + public void testGetInOutEdges() { + for(Integer v : graph.getVertices()) { + Collection incident = graph.getIncidentEdges(v); + Collection in = graph.getInEdges(v); + Collection out = graph.getOutEdges(v); + assertTrue(incident.containsAll(in)); + assertTrue(incident.containsAll(out)); + for(Double e : in) { + if(out.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + for(Double e : out) { + if(in.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + } + + assertEquals(smallGraph.getInEdges(v1).size(), 4); + assertEquals(smallGraph.getOutEdges(v1).size(), 3); + assertEquals(smallGraph.getOutEdges(v0).size(), 2); + } + + public void testGetPredecessors() { + assertTrue(smallGraph.getPredecessors(v0).containsAll(Collections.singleton(v1))); + } + + public void testGetSuccessors() { + assertTrue(smallGraph.getPredecessors(v1).contains(v0)); + assertTrue(smallGraph.getPredecessors(v1).contains(v2)); + } + + public void testGetNeighbors() { + Collection neighbors = smallGraph.getNeighbors(v1); + assertTrue(neighbors.contains(v0)); + assertTrue(neighbors.contains(v2)); + } + + public void testGetIncidentEdges() { + assertEquals(smallGraph.getIncidentEdges(v0).size(), 2); + } + + public void testFindEdge() { + Number edge = smallGraph.findEdge(v1, v2); + assertTrue(edge == e12 || edge == e21); + } + + public void testGetEndpoints() { + Pair endpoints = smallGraph.getEndpoints(e01); + assertTrue((endpoints.getFirst() == v0 && endpoints.getSecond() == v1) || + endpoints.getFirst() == v1 && endpoints.getSecond() == v0); + } + + public void testIsDirected() { + for(Double edge : smallGraph.getEdges()) { + if(edge == e21) { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.DIRECTED); + } else { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.UNDIRECTED); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseMultigraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,160 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public abstract class AbstractSparseMultigraphTest extends TestCase { + + protected Integer v0 = 0; + protected Integer v1 = 1; + protected Integer v2 = 2; + protected Number e01 = .1; + protected Number e10 = .2; + protected Number e12 = .3; + protected Number e21 = .4; + + protected Supplier vertexFactory = new Supplier() { + int v=0; + public Number get() { + return v++; + } + }; + protected Supplier edgeFactory = new Supplier() { + int e=0; + public Number get() { + return e++; + } + }; + + protected Graph graph; + protected int vertexCount = 50; + protected Graph smallGraph; + + public void testGetEdges() { + assertEquals(smallGraph.getEdgeCount(), 4); + } + + public void testGetVertices() { + assertEquals(smallGraph.getVertexCount(), 3); + } + + public void testAddVertex() { + int count = graph.getVertexCount(); + graph.addVertex(count); + assertEquals(graph.getVertexCount(), count+1); + } + + public void testRemoveEndVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount-1); + graph.removeVertex(vertexCount-1); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testRemoveMiddleVertex() { + int vertexCount = graph.getVertexCount(); + int edgeCount = graph.getEdgeCount(); + Collection incident = graph.getIncidentEdges(vertexCount/2); + graph.removeVertex(vertexCount/2); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(edgeCount - incident.size(), graph.getEdgeCount()); + } + + public void testAddEdge() { + int edgeCount = graph.getEdgeCount(); + graph.addEdge(edgeFactory.get(), 0, 1); + assertEquals(graph.getEdgeCount(), edgeCount+1); + } + + public void testNullEndpoint() { + try { + graph.addEdge(edgeFactory.get(), new Pair(1,null)); + fail("should not be able to add an edge with a null endpoint"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + + public void testRemoveEdge() { + List edgeList = new ArrayList(graph.getEdges()); + int edgeCount = graph.getEdgeCount(); + graph.removeEdge(edgeList.get(edgeList.size()/2)); + assertEquals(graph.getEdgeCount(), edgeCount-1); + } + + public void testGetInOutEdges() { + for(Number v : graph.getVertices()) { + Collection incident = graph.getIncidentEdges(v); + Collection in = graph.getInEdges(v); + Collection out = graph.getOutEdges(v); + assertTrue(incident.containsAll(in)); + assertTrue(incident.containsAll(out)); + for(Number e : in) { + if(out.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + for(Number e : out) { + if(in.contains(e)) { + assertTrue(graph.getEdgeType(e) == EdgeType.UNDIRECTED); + } + } + } + + assertEquals(smallGraph.getInEdges(v1).size(), 4); + assertEquals(smallGraph.getOutEdges(v1).size(), 3); + assertEquals(smallGraph.getOutEdges(v0).size(), 2); + } + + public void testGetPredecessors() { + assertTrue(smallGraph.getPredecessors(v0).containsAll(Collections.singleton(v1))); + } + + public void testGetSuccessors() { + assertTrue(smallGraph.getPredecessors(v1).contains(v0)); + assertTrue(smallGraph.getPredecessors(v1).contains(v2)); + } + + public void testGetNeighbors() { + Collection neighbors = smallGraph.getNeighbors(v1); + assertTrue(neighbors.contains(v0)); + assertTrue(neighbors.contains(v2)); + } + + public void testGetIncidentEdges() { + assertEquals(smallGraph.getIncidentEdges(v0).size(), 2); + } + + public void testFindEdge() { + Number edge = smallGraph.findEdge(v1, v2); + assertTrue(edge == e12 || edge == e21); + } + + public void testGetEndpoints() { + Pair endpoints = smallGraph.getEndpoints(e01); + assertTrue((endpoints.getFirst() == v0 && endpoints.getSecond() == v1) || + endpoints.getFirst() == v1 && endpoints.getSecond() == v0); + } + + public void testIsDirected() { + for(Number edge : smallGraph.getEdges()) { + if(edge == e21) { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.DIRECTED); + } else { + assertEquals(smallGraph.getEdgeType(edge), EdgeType.UNDIRECTED); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseTreeTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseTreeTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseTreeTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractSparseTreeTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,104 @@ +package edu.uci.ics.jung.graph; + +import junit.framework.TestCase; + +import com.google.common.base.Supplier; + + +public abstract class AbstractSparseTreeTest extends TestCase { + + protected Tree tree; + protected Supplier> graphFactory; + protected Supplier edgeFactory; + + public void testRemoveVertex() { + tree.addVertex("A"); + tree.addEdge(edgeFactory.get(), "A", "B"); + tree.addEdge(edgeFactory.get(), "A", "C"); + tree.addEdge(edgeFactory.get(), "B", "E"); + tree.addEdge(edgeFactory.get(), "B", "F"); +// System.err.println("tree is "+tree); + tree.removeVertex("B"); +// System.err.println("tree now "+tree); + } + + public void testSimpleTree() { + tree.addVertex("A"); + tree.addEdge(edgeFactory.get(), "A", "B"); + tree.addEdge(edgeFactory.get(), "A", "C"); + } + + public void testCreateLoop() { + try { + tree.addVertex("A"); + tree.addEdge(edgeFactory.get(), "A", "A"); + fail("should not be able to addChild(v,v)"); + } catch(IllegalArgumentException e) { + // all is well + } + try { + tree.addEdge(edgeFactory.get(), "A", "B"); + tree.addEdge(edgeFactory.get(), "B", "A"); + fail("should not allow loop"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + public void testHeightAndDepth() { + tree.addVertex("V0"); + assertEquals(tree.getHeight(), 0); + assertEquals(tree.getDepth("V0"), 0); + tree.addEdge(edgeFactory.get(), "V0", "V1"); + assertEquals(tree.getHeight(), 1); + assertEquals(tree.getDepth("V1"), 1); + tree.addEdge(edgeFactory.get(), "V0", "V2"); + assertEquals(tree.getHeight(), 1); + assertEquals(tree.getDepth("V2"), 1); + tree.addEdge(edgeFactory.get(), "V1", "V4"); + assertEquals(tree.getHeight(), 2); + assertEquals(tree.getDepth("V4"), 2); + tree.addEdge(edgeFactory.get(), "V2", "V3"); + assertEquals(tree.getHeight(), 2); + assertEquals(tree.getDepth("V3"), 2); + tree.addEdge(edgeFactory.get(), "V2", "V5"); + assertEquals(tree.getHeight(), 2); + assertEquals(tree.getDepth("V5"), 2); + tree.addEdge(edgeFactory.get(), "V4", "V6"); + assertEquals(tree.getHeight(), 3); + assertEquals(tree.getDepth("V6"), 3); + tree.addEdge(edgeFactory.get(), "V4", "V7"); + assertEquals(tree.getHeight(), 3); + assertEquals(tree.getDepth("V7"), 3); + tree.addEdge(edgeFactory.get(), "V3", "V8"); + assertEquals(tree.getHeight(), 3); + assertEquals(tree.getDepth("V8"), 3); + tree.addEdge(edgeFactory.get(), "V6", "V9"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V9"), 4); + tree.addEdge(edgeFactory.get(), "V4", "V10"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V10"), 3); + tree.addEdge(edgeFactory.get(), "V4", "V11"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V11"), 3); + tree.addEdge(edgeFactory.get(), "V4", "V12"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V12"), 3); + tree.addEdge(edgeFactory.get(), "V6", "V13"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V13"), 4); + tree.addEdge(edgeFactory.get(), "V10", "V14"); + assertEquals(tree.getHeight(), 4); + assertEquals(tree.getDepth("V14"), 4); + tree.addEdge(edgeFactory.get(), "V13", "V15"); + assertEquals(tree.getHeight(), 5); + assertEquals(tree.getDepth("V15"), 5); + tree.addEdge(edgeFactory.get(), "V13", "V16"); + assertEquals(tree.getHeight(), 5); + assertEquals(tree.getDepth("V16"), 5); + + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractTreeUtilsTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractTreeUtilsTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractTreeUtilsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractTreeUtilsTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,43 @@ +package edu.uci.ics.jung.graph; + +import junit.framework.TestCase; +import edu.uci.ics.jung.graph.util.TreeUtils; + +public abstract class AbstractTreeUtilsTest extends TestCase { + + protected Tree tree; + + public void testRemove() { + try { + TreeUtils.getSubTree(tree, "C0"); + tree.removeVertex("C0"); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void testAdd() { + try { + Forest subTree = TreeUtils.getSubTree(tree, "C0"); + Integer edge = tree.getInEdges("C0").iterator().next(); + String parent = tree.getPredecessors("C0").iterator().next(); + tree.removeVertex("C0"); + + TreeUtils.addSubTree(tree, subTree, parent, edge); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractUndirectedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractUndirectedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractUndirectedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/AbstractUndirectedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,124 @@ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; + +import junit.framework.TestCase; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public abstract class AbstractUndirectedSparseMultigraphTest extends TestCase { + + protected Integer v0 = new Integer(0); + protected Integer v1 = new Integer(1); + protected Integer v2 = new Integer(2); + + protected Float e01 = new Float(.1f); + protected Float e10 = new Float(.2f); + protected Float e12 = new Float(.3f); + protected Float e21 = new Float(.4f); + + protected Graph graph; + + public void testGetEdges() { + assertEquals(graph.getEdgeCount(), 4); + } + + public void testGetVertices() { + assertEquals(graph.getVertexCount(), 3); + } + + public void testAddVertex() { + int count = graph.getVertexCount(); + graph.addVertex(new Integer(3)); + assertEquals(graph.getVertexCount(), count+1); + } + + public void testRemoveEndVertex() { + int vertexCount = graph.getVertexCount(); + graph.removeVertex(v0); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(2, graph.getEdgeCount()); + } + + public void testRemoveMiddleVertex() { + int vertexCount = graph.getVertexCount(); + graph.removeVertex(v1); + assertEquals(vertexCount-1, graph.getVertexCount()); + assertEquals(0, graph.getEdgeCount()); + } + + public void testAddEdge() { + int edgeCount = graph.getEdgeCount(); + graph.addEdge(new Double(.5), v0, v1); + assertEquals(graph.getEdgeCount(), edgeCount+1); + } + + public void testRemoveEdge() { + int edgeCount = graph.getEdgeCount(); + graph.removeEdge(e12); + assertEquals(graph.getEdgeCount(), edgeCount-1); + } + + public void testGetInEdges() { + assertEquals(graph.getInEdges(v1).size(), 4); + } + + public void testGetOutEdges() { + assertEquals(graph.getOutEdges(v1).size(), 4); + } + + public void testGetPredecessors() { + assertTrue(graph.getPredecessors(v0).containsAll(Collections.singleton(v1))); + } + + public void testGetSuccessors() { + assertTrue(graph.getPredecessors(v1).contains(v0)); + assertTrue(graph.getPredecessors(v1).contains(v2)); + } + + public void testGetNeighbors() { + Collection neighbors = graph.getNeighbors(v1); + assertTrue(neighbors.contains(v0)); + assertTrue(neighbors.contains(v2)); + } + + public void testGetIncidentEdges() { + assertEquals(graph.getIncidentEdges(v0).size(), 2); + } + + public void testFindEdge() { + Number edge = graph.findEdge(v1, v2); + assertTrue(edge == e12 || edge == e21); + } + + public void testNullEndpoint() { + try { + graph.addEdge(.99, new Pair(1,null)); + fail("should not be able to add an edge with a null endpoint"); + } catch(IllegalArgumentException e) { + // all is well + } + } + + public void testGetEndpoints() { + Pair endpoints = graph.getEndpoints(e01); + assertTrue((endpoints.getFirst() == v0 && endpoints.getSecond() == v1) || + endpoints.getFirst() == v1 && endpoints.getSecond() == v0); + } + + public void testIsDirected() { + for(Number edge : graph.getEdges()) { + assertEquals(graph.getEdgeType(edge), EdgeType.UNDIRECTED); + } + } + + public void testAddDirectedEdge() { + try { + graph.addEdge(new Float(.9), v1, v2, EdgeType.DIRECTED); + fail("Cannot add a directed edge to this graph"); + } catch(IllegalArgumentException uoe) { + // all is well + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/util/PairTest.java libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/util/PairTest.java --- libjung-free-java-2.0.1+dfsg/jung-api/src/test/java/edu/uci/ics/jung/graph/util/PairTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-api/src/test/java/edu/uci/ics/jung/graph/util/PairTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,118 @@ +package edu.uci.ics.jung.graph.util; + +import java.util.ArrayList; +import java.util.List; + +import edu.uci.ics.jung.graph.util.Pair; + +import junit.framework.TestCase; + +public class PairTest extends TestCase { + + Pair pair; + + + @Override + protected void setUp() throws Exception { + pair = new Pair(1,2); + super.setUp(); + } + + public void testGetFirst() { + assertEquals(pair.getFirst(), 1); + } + + public void testGetSecond() { + assertEquals(pair.getSecond(), 2); + } + + public void testEqualsObject() { + Pair ipair = new Pair(1,2); + assertTrue(pair.equals(ipair)); + } + + public void testAdd() { + try { + pair.add(3); + fail("should not be able to add to Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testAddAll() { + try { + List list = new ArrayList(pair); + pair.addAll(list); + fail("should not be able to addAll to Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testClear() { + try { + pair.clear(); + fail("should not be able to clear a Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testContains() { + assertTrue(pair.contains(1)); + } + + public void testContainsAll() { + List list = new ArrayList(pair); + assertTrue(pair.containsAll(list)); + } + + public void testIsEmpty() { + assertFalse(pair.isEmpty()); + } + + public void testRemove() { + try { + pair.remove(1); + fail("should not be able to remove from a Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testRemoveAll() { + try { + List list = new ArrayList(pair); + pair.removeAll(list); + fail("should not be able to removeAll from Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testRetainAll() { + try { + List list = new ArrayList(pair); + pair.retainAll(list); + fail("should not be able to retainAll from Pair"); + } catch(Exception e) { + // all is well + } + } + + public void testSize() { + assertEquals(pair.size(), 2); + } + + public void testToArray() { + @SuppressWarnings("unused") + Object[] arr = pair.toArray(); + } + + public void testToArraySArray() { + @SuppressWarnings("unused") + Integer[] arr = pair.toArray(new Integer[2]); + } + +} Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-api-2.0.1-sources.jar and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-api-2.0.1-sources.jar differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/assembly.xml libjung-free-java-2.1.1/jung-graph-impl/assembly.xml --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/assembly.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/assembly.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + dependencies + + tar.gz + + false + + + / + + + + + / + false + runtime + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/pom.xml libjung-free-java-2.1.1/jung-graph-impl/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,32 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-graph-impl + JUNG - Graph Implementations + Graph implementations for the JUNG project + + + + net.sf.jung + jung-api + ${project.version} + + + net.sf.jung + jung-api + ${project.version} + test-jar + test + + + junit + junit + test + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractGraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractGraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,244 @@ +/* + * Created on Apr 2, 2006 + * + * Copyright (c) 2006, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Abstract implementation of the Graph interface. + * Designed to simplify implementation of new graph classes. + * + * @author Joshua O'Madadhain + */ +@SuppressWarnings("serial") +public abstract class AbstractGraph implements Graph, Serializable +{ + public boolean addEdge(E edge, Collection vertices) + { + return addEdge(edge, vertices, this.getDefaultEdgeType()); + } + + @SuppressWarnings("unchecked") + public boolean addEdge(E edge, Collection vertices, EdgeType edgeType) { + if (vertices == null) + throw new IllegalArgumentException("'vertices' parameter must not be null"); + if (vertices.size() == 2) + return addEdge(edge, + vertices instanceof Pair ? (Pair)vertices : new Pair(vertices), + edgeType); + else if (vertices.size() == 1) + { + V vertex = vertices.iterator().next(); + return addEdge(edge, new Pair(vertex, vertex), edgeType); + } + else + throw new IllegalArgumentException("Graph objects connect 1 or 2 vertices; vertices arg has " + vertices.size()); + } + + public boolean addEdge(E e, V v1, V v2) + { + return addEdge(e, v1, v2, this.getDefaultEdgeType()); + } + + public boolean addEdge(E e, V v1, V v2, EdgeType edge_type) + { + return addEdge(e, new Pair(v1, v2), edge_type); + } + + /** + * Adds {@code edge} to this graph with the specified {@code endpoints}, + * with the default edge type. + * + * @param edge the edge to be added + * @param endpoints the endpoints to be connected to this edge + * @return {@code true} iff the graph was modified as a result of this call + */ + public boolean addEdge(E edge, Pair endpoints) + { + return addEdge(edge, endpoints, this.getDefaultEdgeType()); + } + + /** + * Adds {@code edge} to this graph with the specified {@code endpoints} + * and {@code EdgeType}. + * + * @param edge the edge to be added + * @param endpoints the endpoints to be connected to this edge + * @param edgeType the type of edge to add + * @return {@code} true iff the graph was modified as a result of this call + */ + public abstract boolean addEdge(E edge, Pair endpoints, EdgeType edgeType); + + protected Pair getValidatedEndpoints(E edge, Pair endpoints) + { + if (edge == null) + throw new IllegalArgumentException("input edge may not be null"); + + if (endpoints == null) + throw new IllegalArgumentException("endpoints may not be null"); + + Pair new_endpoints = new Pair(endpoints.getFirst(), endpoints.getSecond()); + if (containsEdge(edge)) + { + Pair existing_endpoints = getEndpoints(edge); + if (!existing_endpoints.equals(new_endpoints)) { + throw new IllegalArgumentException("edge " + edge + + " already exists in this graph with endpoints " + existing_endpoints + + " and cannot be added with endpoints " + endpoints); + } else { + return null; + } + } + return new_endpoints; + } + + public int inDegree(V vertex) + { + return this.getInEdges(vertex).size(); + } + + public int outDegree(V vertex) + { + return this.getOutEdges(vertex).size(); + } + + public boolean isPredecessor(V v1, V v2) + { + return this.getPredecessors(v1).contains(v2); + } + + public boolean isSuccessor(V v1, V v2) + { + return this.getSuccessors(v1).contains(v2); + } + + public int getPredecessorCount(V vertex) + { + return this.getPredecessors(vertex).size(); + } + + public int getSuccessorCount(V vertex) + { + return this.getSuccessors(vertex).size(); + } + + public boolean isNeighbor(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + throw new IllegalArgumentException("At least one of these not in this graph: " + v1 + ", " + v2); + return this.getNeighbors(v1).contains(v2); + } + + public boolean isIncident(V vertex, E edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + throw new IllegalArgumentException("At least one of these not in this graph: " + vertex + ", " + edge); + return this.getIncidentEdges(vertex).contains(edge); + } + + public int getNeighborCount(V vertex) + { + if (!containsVertex(vertex)) + throw new IllegalArgumentException(vertex + " is not a vertex in this graph"); + return this.getNeighbors(vertex).size(); + } + + public int degree(V vertex) + { + if (!containsVertex(vertex)) + throw new IllegalArgumentException(vertex + " is not a vertex in this graph"); + return this.getIncidentEdges(vertex).size(); + } + + public int getIncidentCount(E edge) + { + Pair incident = this.getEndpoints(edge); + if (incident == null) + return 0; + if (incident.getFirst() == incident.getSecond()) + return 1; + else + return 2; + } + + public V getOpposite(V vertex, E edge) + { + Pair incident = this.getEndpoints(edge); + V first = incident.getFirst(); + V second = incident.getSecond(); + if (vertex.equals(first)) + return second; + else if (vertex.equals(second)) + return first; + else + throw new IllegalArgumentException(vertex + " is not incident to " + edge + " in this graph"); + } + + public E findEdge(V v1, V v2) + { + for (E e : getOutEdges(v1)) + { + if (getOpposite(v1, e).equals(v2)) + return e; + } + return null; + } + + public Collection findEdgeSet(V v1, V v2) + { + if (!getVertices().contains(v1)) + throw new IllegalArgumentException(v1 + " is not an element of this graph"); + + if (!getVertices().contains(v2)) + throw new IllegalArgumentException(v2 + " is not an element of this graph"); + + Collection edges = new ArrayList(); + for (E e : getOutEdges(v1)) + { + if (getOpposite(v1, e).equals(v2)) + edges.add(e); + } + return Collections.unmodifiableCollection(edges); + } + + public Collection getIncidentVertices(E edge) + { + Pair endpoints = this.getEndpoints(edge); + Collection incident = new ArrayList(); + incident.add(endpoints.getFirst()); + incident.add(endpoints.getSecond()); + + return Collections.unmodifiableCollection(incident); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer("Vertices:"); + for(V v : getVertices()) { + sb.append(v+","); + } + sb.setLength(sb.length()-1); + sb.append("\nEdges:"); + for(E e : getEdges()) { + Pair ep = getEndpoints(e); + sb.append(e+"["+ep.getFirst()+","+ep.getSecond()+"] "); + } + return sb.toString(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractTypedGraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractTypedGraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractTypedGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/AbstractTypedGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Sep 1, 2008 + * + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; + +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * An abstract class for graphs whose edges all have the same {@code EdgeType}. + * Intended to simplify the implementation of such graph classes. + */ +@SuppressWarnings("serial") +public abstract class AbstractTypedGraph extends AbstractGraph +{ + /** + * The edge type for all edges in this graph. + */ + protected final EdgeType edge_type; + + /** + * Creates an instance with the specified edge type. + * @param edge_type the type of edges that this graph accepts + */ + public AbstractTypedGraph(EdgeType edge_type) + { + this.edge_type = edge_type; + } + + /** + * Returns this graph's edge type. + */ + public EdgeType getDefaultEdgeType() + { + return this.edge_type; + } + + /** + * Returns this graph's edge type, or {@code null} if {@code e} is not + * in this graph. + */ + public EdgeType getEdgeType(E e) + { + return hasEqualEdgeType(edge_type) ? this.edge_type : null; + } + + /** + * Returns the edge set for this graph if {@code edgeType} matches the + * edge type for this graph, and an empty set otherwise. + */ + public Collection getEdges(EdgeType edge_type) + { + return hasEqualEdgeType(edge_type) ? this.getEdges() : Collections.emptySet(); + } + + /** + * Returns the edge count for this graph if {@code edge_type} matches + * the edge type for this graph, and 0 otherwise. + */ + public int getEdgeCount(EdgeType edge_type) + { + return hasEqualEdgeType(edge_type) ? this.getEdgeCount() : 0; + } + + /** + * @param edge_type the edge type to compare to this instance's default edge type + * @return {@code true} if {@code edge_type} matches the default edge type for + * this graph, and {@code false} otherwise + */ + protected boolean hasEqualEdgeType(EdgeType edge_type) + { + return this.edge_type.equals(edge_type); + } + + /** + * Throws an {@code IllegalArgumentException} if {@code edge_type} does not + * match the default edge type for this graph. + * @param edge_type the edge type to compare to this instance's default edge type + */ + protected void validateEdgeType(EdgeType edge_type) + { + if (!hasEqualEdgeType(edge_type)) + throw new IllegalArgumentException("Edge type '" + edge_type + + "' does not match the default edge type for this graph: '" + + this.edge_type + "'"); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateForest.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateForest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateForest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateForest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,339 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.graph.util.TreeUtils; + +/** + * An implementation of Forest that delegates to a specified DirectedGraph + * instance. + * @author Tom Nelson + * + * @param the vertex type + * @param the edge type + */ +@SuppressWarnings("serial") +public class DelegateForest extends GraphDecorator implements Forest +{ + /** + * Creates an instance backed by a new {@code DirectedSparseGraph} instance. + */ + public DelegateForest() { + this(new DirectedSparseGraph()); + } + + /** + * Creates an instance backed by the input {@code DirectedGraph}. + * @param delegate the graph to which operations will be delegated + */ + public DelegateForest(DirectedGraph delegate) { + super(delegate); + } + + /** + * Add an edge to the tree, connecting v1, the parent and v2, the child. + * v1 must already exist in the tree, and v2 must not already exist + * the passed edge must be unique in the tree. Passing an edgeType + * other than EdgeType.DIRECTED may cause an illegal argument exception + * in the delegate graph. + * + * @param e a unique edge to add + * @param v1 the parent node + * @param v2 the child node + * @param edgeType should be EdgeType.DIRECTED + * @return true if this call mutates the underlying graph + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType) + */ + @Override + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + if(delegate.getVertices().contains(v1) == false) { + throw new IllegalArgumentException("Tree must already contain "+v1); + } + if(delegate.getVertices().contains(v2)) { + throw new IllegalArgumentException("Tree must not already contain "+v2); + } + return delegate.addEdge(e, v1, v2, edgeType); + } + + /** + * Add vertex as a root of the tree + * + * @param vertex the tree root to add + * @return true if this call mutates the underlying graph + * @see edu.uci.ics.jung.graph.Graph#addVertex(java.lang.Object) + */ + @Override + public boolean addVertex(V vertex) { + setRoot(vertex); + return true; + } + + /** + * Removes edge from this tree, and the subtree rooted + * at the child vertex incident to edge. + * (The subtree is removed to ensure that the tree in which the edge + * was found is still a tree rather than a forest. To change this + * behavior so that the + * @param edge the edge to remove + * @return true iff the tree was modified + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + @Override + public boolean removeEdge(E edge) { + return removeEdge(edge, true); + } + + /** + * Removes edge from this tree. + * If remove_subtree is true, removes + * the subtree rooted at the child vertex incident to edge. + * Otherwise, leaves the subtree intact as a new component tree of this + * forest. + * @param edge the edge to remove + * @param remove_subtree if true, remove the subtree + * @return true iff the tree was modified + */ + public boolean removeEdge(E edge, boolean remove_subtree) + { + if (!delegate.containsEdge(edge)) + return false; + V child = getDest(edge); + if (remove_subtree) + return removeVertex(child); + else + { + delegate.removeEdge(edge); + return false; + } + } + + /** + * Removes vertex from this tree, and the subtree + * rooted at vertex. + * @param vertex the vertex to remove + * @return true iff the tree was modified + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + @Override + public boolean removeVertex(V vertex) { + return removeVertex(vertex, true); + } + + /** + * Removes vertex from this tree. + * If remove_subtrees is true, removes + * the subtrees rooted at the children of vertex. + * Otherwise, leaves these subtrees intact as new component trees of this + * forest. + * @param vertex the vertex to remove + * @param remove_subtrees if true, remove the subtrees + * rooted at vertex's children + * @return true iff the tree was modified + */ + public boolean removeVertex(V vertex, boolean remove_subtrees) + { + if (!delegate.containsVertex(vertex)) + return false; + if (remove_subtrees) + for(V v : new ArrayList(delegate.getSuccessors(vertex))) + removeVertex(v, true); + return delegate.removeVertex(vertex); + } + + /** + * returns an ordered list of the nodes beginning at the root + * and ending at the passed child node, including all intermediate + * nodes. + * @param child the last node in the path from the root + * @return an ordered list of the nodes from root to child + */ + public List getPath(V child) { + if (!delegate.containsVertex(child)) + return null; + List list = new ArrayList(); + list.add(child); + V parent = getParent(child); + while(parent != null) { + list.add(list.size(), parent); + parent = getParent(parent); + } + return list; + } + + public V getParent(V child) { + if (!delegate.containsVertex(child)) + return null; + Collection parents = delegate.getPredecessors(child); + if(parents.size() > 0) { + return parents.iterator().next(); + } + return null; + } + + /** + * @return the root of the tree, or null if the tree has > 1 roots + */ + public V getRoot() { + V root = null; + for (V v : delegate.getVertices()) { + if (delegate.getPredecessorCount(v) == 0) { + if (root == null) { + root = v; + } else { + // we've found > 1 root, return null + return null; + } + } + } + return root; + } + + /** + * adds root as a root of the tree + * @param root the initial tree root + */ + public void setRoot(V root) { + delegate.addVertex(root); + } + + /** + * removes a node from the tree, causing all descendants of + * the removed node also to be removed + * @param orphan the node to remove + * @return whether this call mutates the underlying graph + */ + public boolean removeChild(V orphan) { + return removeVertex(orphan); + } + + /** + * computes and returns the depth of the tree from the + * root to the passed vertex + * + * @param v the node who's depth is computed + * @return the depth to the passed node. + */ + public int getDepth(V v) { + return getPath(v).size(); + } + + /** + * computes and returns the height of the tree + * + * @return the height + */ + public int getHeight() { + int height = 0; + for(V v : getVertices()) { + height = Math.max(height, getDepth(v)); + } + return height; + } + + /** + * @param v the vertex to test + * @return true if v is neither a leaf + * nor a root + */ + public boolean isInternal(V v) { + return isLeaf(v) == false && isRoot(v) == false; + } + + /** + * @param v the vertex to test + * @return {@code true} if {@code v} has no child nodes. + */ + public boolean isLeaf(V v) { + return getChildren(v).size() == 0; + } + + /** + * @param v the vertex whose children are to be returned + * @return the children of {@code v}. + */ + public Collection getChildren(V v) { + return delegate.getSuccessors(v); + } + + /** + * @param v the vertex to test + * @return {@code true} if {@code v} has no parent node. + */ + public boolean isRoot(V v) { + return getParent(v) == null; + } + + @Override + public int getIncidentCount(E edge) + { + return 2; + } + + @SuppressWarnings("unchecked") + @Override + public boolean addEdge(E edge, Collection vertices) { + Pair pair = null; + if(vertices instanceof Pair) { + pair = (Pair)vertices; + } else { + pair = new Pair(vertices); + } + return addEdge(edge, pair.getFirst(), pair.getSecond()); + } + + /** + * @return the root of each tree of this forest as a {@code Collection}. + */ + public Collection getRoots() { + Collection roots = new HashSet(); + for(V v : delegate.getVertices()) { + if(delegate.getPredecessorCount(v) == 0) { + roots.add(v); + } + } + return roots; + } + + public Collection> getTrees() { + Collection> trees = new HashSet>(); + for(V v : getRoots()) { + Tree tree = new DelegateTree(); + tree.addVertex(v); + TreeUtils.growSubTree(this, tree, v); + trees.add(tree); + } + return trees; + } + + /** + * Adds {@code tree} to this graph as an element of this forest. + * + * @param tree the tree to add to this forest as a component + */ + public void addTree(Tree tree) { + TreeUtils.addSubTree(this, tree, null, null); + } + + public int getChildCount(V vertex) + { + return delegate.getSuccessorCount(vertex); + } + + public Collection getChildEdges(V vertex) + { + return delegate.getOutEdges(vertex); + } + + public E getParentEdge(V vertex) + { + if (isRoot(vertex)) + return null; + return delegate.getInEdges(vertex).iterator().next(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateTree.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateTree.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateTree.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DelegateTree.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,361 @@ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Tree that delegates to + * a specified instance of DirectedGraph. + * @author Tom Nelson + * + * @param the vertex type + * @param the edge type + */ +@SuppressWarnings("serial") +public class DelegateTree extends GraphDecorator implements Tree +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static final Supplier> getFactory() { + return new Supplier> () { + public Tree get() { + return new DelegateTree(new DirectedSparseMultigraph()); + } + }; + } + + protected V root; + protected Map vertex_depths; + + /** + * Creates an instance. + */ + public DelegateTree() { + this(DirectedSparseMultigraph.getFactory()); + } + + /** + * create an instance with passed values. + * @param graphFactory must create a DirectedGraph to use as a delegate + */ + public DelegateTree(Supplier> graphFactory) { + super(graphFactory.get()); + this.vertex_depths = new HashMap(); + } + + /** + * Creates a new DelegateTree which delegates to graph. + * Assumes that graph is already a tree; if it's not, future behavior + * of this instance is undefined. + * @param graph the graph to which this instance will delegate operations. + */ + public DelegateTree(DirectedGraph graph) { + super(graph); + this.vertex_depths = new HashMap(); + } + + /** + * Add an edge to the tree, connecting v1, the parent and v2, the child. + * v1 must already exist in the tree, and v2 must not already exist + * the passed edge must be unique in the tree. Passing an edgeType + * other than EdgeType.DIRECTED may cause an illegal argument exception + * in the delegate graph. + * + * @param e a unique edge to add + * @param v1 the parent node + * @param v2 the child node + * @param edgeType should be EdgeType.DIRECTED + * @return true if this call mutates the underlying graph + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType) + */ + @Override + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + return addChild(e, v1, v2, edgeType); + } + + /** + * Add an edge to the tree, connecting v1, the parent and v2, the child. + * v1 must already exist in the tree, and v2 must not already exist + * the passed edge must be unique in the tree. + * + * @param e a unique edge to add + * @param v1 the parent node + * @param v2 the child node + * @return true if this call mutates the underlying graph + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object) + */ + @Override + public boolean addEdge(E e, V v1, V v2) { + return addChild(e, v1, v2); + } + + /** + * Will set the root of the Tree, only if the Tree is empty and the + * root is currently unset. + * + * @param vertex the tree root to set + * @return true if this call mutates the underlying graph + * @see edu.uci.ics.jung.graph.Graph#addVertex(java.lang.Object) + * @throws UnsupportedOperationException if the root was previously set + */ + @Override + public boolean addVertex(V vertex) { + if(root == null) { + this.root = vertex; + vertex_depths.put(vertex, 0); + return delegate.addVertex(vertex); + } else { + throw new UnsupportedOperationException("Unless you are setting the root, use addChild()"); + } + } + + /** + * remove the passed node, and all nodes that are descendants of the + * passed node. + * @param vertex the vertex to remove + * @return true iff the tree was modified + * @see edu.uci.ics.jung.graph.Graph#removeVertex(java.lang.Object) + */ + @Override + public boolean removeVertex(V vertex) { + if (!delegate.containsVertex(vertex)) + return false; + for(V v : getChildren(vertex)) { + removeVertex(v); + vertex_depths.remove(v); + } + + // recalculate height + vertex_depths.remove(vertex); + return delegate.removeVertex(vertex); + } + + /** + * add the passed child node as a child of parent. + * parent must exist in the tree, and child must not already exist. + * + * @param edge the unique edge to connect the parent and child nodes + * @param parent the existing parent to attach the child to + * @param child the new child to add to the tree as a child of parent + * @param edgeType must be EdgeType.DIRECTED or the underlying graph may throw an exception + * @return whether this call mutates the underlying graph + */ + public boolean addChild(E edge, V parent, V child, EdgeType edgeType) { + Collection vertices = delegate.getVertices(); + if(vertices.contains(parent) == false) { + throw new IllegalArgumentException("Tree must already contain parent "+parent); + } + if(vertices.contains(child)) { + throw new IllegalArgumentException("Tree must not already contain child "+child); + } + vertex_depths.put(child, vertex_depths.get(parent) + 1); + return delegate.addEdge(edge, parent, child, edgeType); + } + + /** + * add the passed child node as a child of parent. + * parent must exist in the tree, and child must not already exist + * @param edge the unique edge to connect the parent and child nodes + * @param parent the existing parent to attach the child to + * @param child the new child to add to the tree as a child of parent + * @return whether this call mutates the underlying graph + */ + public boolean addChild(E edge, V parent, V child) { + Collection vertices = delegate.getVertices(); + if(vertices.contains(parent) == false) { + throw new IllegalArgumentException("Tree must already contain parent "+parent); + } + if(vertices.contains(child)) { + throw new IllegalArgumentException("Tree must not already contain child "+child); + } + vertex_depths.put(child, vertex_depths.get(parent) + 1); + return delegate.addEdge(edge, parent, child); + } + + /** + * get the number of children of the passed parent node + */ + public int getChildCount(V parent) { + if (!delegate.containsVertex(parent)) + return 0; + return getChildren(parent).size(); + } + + /** + * get the immediate children nodes of the passed parent + */ + public Collection getChildren(V parent) { + if (!delegate.containsVertex(parent)) + return null; + return delegate.getSuccessors(parent); + } + + /** + * get the single parent node of the passed child + */ + public V getParent(V child) { + if (!delegate.containsVertex(child)) + return null; + Collection predecessors = delegate.getPredecessors(child); + if(predecessors.size() == 0) { + return null; + } + return predecessors.iterator().next(); + } + + /** + * Returns an ordered list of the nodes beginning at the root + * and ending at {@code vertex}, including all intermediate + * nodes. + * @param vertex the last node in the path from the root + * @return an ordered list of the nodes from root to child + */ + public List getPath(V vertex) { + if (!delegate.containsVertex(vertex)) + return null; + List vertex_to_root = new ArrayList(); + vertex_to_root.add(vertex); + V parent = getParent(vertex); + while(parent != null) { + vertex_to_root.add(parent); + parent = getParent(parent); + } + // reverse list so that it goes from root to child + List root_to_vertex = new ArrayList(vertex_to_root.size()); + for (int i = vertex_to_root.size() - 1; i >= 0; i--) + root_to_vertex.add(vertex_to_root.get(i)); + return root_to_vertex; + } + + /** + * getter for the root of the tree + * @return the root + */ + public V getRoot() { + return root; + } + + /** + * sets the root to the passed value, only if the root is + * previously unset + * @param root the initial tree root + */ + public void setRoot(V root) { + addVertex(root); + } + + /** + * removes a node from the tree, causing all descendants of + * the removed node also to be removed + * @param orphan the node to remove + * @return whether this call mutates the underlying graph + */ + public boolean removeChild(V orphan) { + return removeVertex(orphan); + } + + /** + * computes and returns the depth of the tree from the + * root to the passed vertex + * + * @param v the node who's depth is computed + * @return the depth to the passed node. + */ + public int getDepth(V v) { + return this.vertex_depths.get(v); + } + + /** + * Computes and returns the height of the tree. + * + * @return the height + */ + public int getHeight() { + int height = 0; + for(V v : getVertices()) { + height = Math.max(height, getDepth(v)); + } + return height; + } + + /** + * @param v the vertex to test + * @return true if v is neither + * a leaf nor the root of this tree + */ + public boolean isInternal(V v) { + if (!delegate.containsVertex(v)) + return false; + return isLeaf(v) == false && isRoot(v) == false; + } + + /** + * @param v the vertex to test + * @return true if {@code v} has no children + */ + public boolean isLeaf(V v) { + if (!delegate.containsVertex(v)) + return false; + return getChildren(v).size() == 0; + } + + /** + * @param v the vertex to test + * @return true if {@code v} has no parent + */ + public boolean isRoot(V v) { + if (!delegate.containsVertex(v)) + return false; + return getParent(v) == null; + } + + @Override + public int getIncidentCount(E edge) + { + if (!delegate.containsEdge(edge)) + return 0; + // all edges in a tree connect exactly 2 vertices + return 2; + } + + @SuppressWarnings("unchecked") + @Override + public boolean addEdge(E edge, Collection vertices) { + Pair pair = null; + if(vertices instanceof Pair) { + pair = (Pair)vertices; + } else { + pair = new Pair(vertices); + } + return addEdge(edge, pair.getFirst(), pair.getSecond()); + } + + @Override + public String toString() { + return "Tree of "+delegate.toString(); + } + + public Collection> getTrees() { + return Collections.>singleton(this); + } + + public Collection getChildEdges(V vertex) { + return getOutEdges(vertex); + } + + public E getParentEdge(V vertex) { + return getInEdges(vertex).iterator().next(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedOrderedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedOrderedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedOrderedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedOrderedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,113 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * An implementation of DirectedGraph, suitable for sparse graphs, + * that orders its vertex and edge collections + * according to insertion time. + */ +@SuppressWarnings("serial") +public class DirectedOrderedSparseMultigraph + extends DirectedSparseMultigraph + implements DirectedGraph, MultiGraph +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + public DirectedGraph get() { + return new DirectedOrderedSparseMultigraph(); + } + }; + } + + /** + * Creates a new instance. + */ + public DirectedOrderedSparseMultigraph() { + vertices = new LinkedHashMap>>(); + edges = new LinkedHashMap>(); + } + + @Override + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertices.put(vertex, new Pair>(new LinkedHashSet(), new LinkedHashSet())); + return true; + } else { + return false; + } + } + + @Override + public Collection getPredecessors(V vertex) { + if (!containsVertex(vertex)) + return null; + Set preds = new LinkedHashSet(); + for (E edge : getIncoming_internal(vertex)) + preds.add(this.getSource(edge)); + + return Collections.unmodifiableCollection(preds); + } + + @Override + public Collection getSuccessors(V vertex) { + if (!containsVertex(vertex)) + return null; + Set succs = new LinkedHashSet(); + for (E edge : getOutgoing_internal(vertex)) + succs.add(this.getDest(edge)); + + return Collections.unmodifiableCollection(succs); + } + + @Override + public Collection getNeighbors(V vertex) { + if (!containsVertex(vertex)) + return null; + Collection neighbors = new LinkedHashSet(); + for (E edge : getIncoming_internal(vertex)) + neighbors.add(this.getSource(edge)); + for (E edge : getOutgoing_internal(vertex)) + neighbors.add(this.getDest(edge)); + return Collections.unmodifiableCollection(neighbors); + } + + @Override + public Collection getIncidentEdges(V vertex) { + if (!containsVertex(vertex)) + return null; + Collection incident = new LinkedHashSet(); + incident.addAll(getIncoming_internal(vertex)); + incident.addAll(getOutgoing_internal(vertex)); + return incident; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseGraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseGraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,289 @@ +/* + * Created on Mar 26, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of DirectedGraph suitable for sparse graphs. + */ +@SuppressWarnings("serial") +public class DirectedSparseGraph extends AbstractTypedGraph implements + DirectedGraph +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static final Supplier> getFactory() { + return new Supplier> () { + public DirectedGraph get() { + return new DirectedSparseGraph(); + } + }; + } + + protected Map>> vertices; // Map of vertices to Pair of adjacency maps {incoming, outgoing} + // of neighboring vertices to incident edges + protected Map> edges; // Map of edges to incident vertex pairs + + /** + * Creates an instance. + */ + public DirectedSparseGraph() + { + super(EdgeType.DIRECTED); + vertices = new HashMap>>(); + edges = new HashMap>(); + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) + { + this.validateEdgeType(edgeType); + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + V source = new_endpoints.getFirst(); + V dest = new_endpoints.getSecond(); + + if (findEdge(source, dest) != null) + return false; + + edges.put(edge, new_endpoints); + + if (!vertices.containsKey(source)) + this.addVertex(source); + + if (!vertices.containsKey(dest)) + this.addVertex(dest); + + // map source of this edge to and vice versa + vertices.get(source).getSecond().put(dest, edge); + vertices.get(dest).getFirst().put(source, edge); + + return true; + } + + @Override + public E findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + return vertices.get(v1).getSecond().get(v2); + } + + @Override + public Collection findEdgeSet(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + ArrayList edge_collection = new ArrayList(1); + E e = findEdge(v1, v2); + if (e == null) + return edge_collection; + edge_collection.add(e); + return edge_collection; + } + + protected Collection getIncoming_internal(V vertex) + { + return vertices.get(vertex).getFirst().values(); + } + + protected Collection getOutgoing_internal(V vertex) + { + return vertices.get(vertex).getSecond().values(); + } + + protected Collection getPreds_internal(V vertex) + { + return vertices.get(vertex).getFirst().keySet(); + } + + protected Collection getSuccs_internal(V vertex) + { + return vertices.get(vertex).getSecond().keySet(); + } + + public Collection getInEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(getIncoming_internal(vertex)); + } + + public Collection getOutEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(getOutgoing_internal(vertex)); + } + + public Collection getPredecessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(getPreds_internal(vertex)); + } + + public Collection getSuccessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(getSuccs_internal(vertex)); + } + + public Pair getEndpoints(E edge) + { + if (!containsEdge(edge)) + return null; + return edges.get(edge); + } + + public V getSource(E directed_edge) + { + if (!containsEdge(directed_edge)) + return null; + return edges.get(directed_edge).getFirst(); + } + + public V getDest(E directed_edge) + { + if (!containsEdge(directed_edge)) + return null; + return edges.get(directed_edge).getSecond(); + } + + public boolean isSource(V vertex, E edge) + { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return vertex.equals(this.getEndpoints(edge).getFirst()); + } + + public boolean isDest(V vertex, E edge) + { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return vertex.equals(this.getEndpoints(edge).getSecond()); + } + + public Collection getEdges() + { + return Collections.unmodifiableCollection(edges.keySet()); + } + + public Collection getVertices() + { + return Collections.unmodifiableCollection(vertices.keySet()); + } + + public boolean containsVertex(V vertex) + { + return vertices.containsKey(vertex); + } + + public boolean containsEdge(E edge) + { + return edges.containsKey(edge); + } + + public int getEdgeCount() + { + return edges.size(); + } + + public int getVertexCount() + { + return vertices.size(); + } + + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Collection neighbors = new HashSet(); + neighbors.addAll(getPreds_internal(vertex)); + neighbors.addAll(getSuccs_internal(vertex)); + return Collections.unmodifiableCollection(neighbors); + } + + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Collection incident_edges = new HashSet(); + incident_edges.addAll(getIncoming_internal(vertex)); + incident_edges.addAll(getOutgoing_internal(vertex)); + return Collections.unmodifiableCollection(incident_edges); + } + + public boolean addVertex(V vertex) + { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertices.put(vertex, new Pair>(new HashMap(), new HashMap())); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) { + if (!containsVertex(vertex)) + return false; + + // copy to avoid concurrent modification in removeEdge + ArrayList incident = new ArrayList(getIncoming_internal(vertex)); + incident.addAll(getOutgoing_internal(vertex)); + + for (E edge : incident) + removeEdge(edge); + + vertices.remove(vertex); + + return true; + } + + public boolean removeEdge(E edge) { + if (!containsEdge(edge)) + return false; + + Pair endpoints = this.getEndpoints(edge); + V source = endpoints.getFirst(); + V dest = endpoints.getSecond(); + + // remove vertices from each others' adjacency maps + vertices.get(source).getSecond().remove(dest); + vertices.get(dest).getFirst().remove(source); + + edges.remove(edge); + return true; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/DirectedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,262 @@ +/* + * Created on Oct 17, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * An implementation of DirectedGraph, suitable for sparse graphs, + * that permits parallel edges. + */ +@SuppressWarnings("serial") +public class DirectedSparseMultigraph + extends AbstractTypedGraph + implements DirectedGraph, MultiGraph { + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + } + + protected Map>> vertices; // Map of vertices to Pair of adjacency sets {incoming, outgoing} + protected Map> edges; // Map of edges to incident vertex pairs + + /** + * Creates a new instance. + */ + public DirectedSparseMultigraph() { + super(EdgeType.DIRECTED); + vertices = new HashMap>>(); + edges = new HashMap>(); + } + + public Collection getEdges() { + return Collections.unmodifiableCollection(edges.keySet()); + } + + public Collection getVertices() { + return Collections.unmodifiableCollection(vertices.keySet()); + } + + public boolean containsVertex(V vertex) { + return vertices.keySet().contains(vertex); + } + + public boolean containsEdge(E edge) { + return edges.keySet().contains(edge); + } + + protected Collection getIncoming_internal(V vertex) + { + return vertices.get(vertex).getFirst(); + } + + protected Collection getOutgoing_internal(V vertex) + { + return vertices.get(vertex).getSecond(); + } + + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertices.put(vertex, new Pair>(new HashSet(), new HashSet())); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) { + if (!containsVertex(vertex)) + return false; + + // copy to avoid concurrent modification in removeEdge + Set incident = new HashSet(getIncoming_internal(vertex)); + incident.addAll(getOutgoing_internal(vertex)); + + for (E edge : incident) + removeEdge(edge); + + vertices.remove(vertex); + + return true; + } + + public boolean removeEdge(E edge) { + if (!containsEdge(edge)) + return false; + + Pair endpoints = this.getEndpoints(edge); + V source = endpoints.getFirst(); + V dest = endpoints.getSecond(); + + // remove edge from incident vertices' adjacency sets + getOutgoing_internal(source).remove(edge); + getIncoming_internal(dest).remove(edge); + + edges.remove(edge); + return true; + } + + + public Collection getInEdges(V vertex) { + if (!containsVertex(vertex)) + return null; + + return Collections.unmodifiableCollection(getIncoming_internal(vertex)); + } + + public Collection getOutEdges(V vertex) { + if (!containsVertex(vertex)) + return null; + + return Collections.unmodifiableCollection(getOutgoing_internal(vertex)); + } + + public Collection getPredecessors(V vertex) { + if (!containsVertex(vertex)) + return null; + + Set preds = new HashSet(); + for (E edge : getIncoming_internal(vertex)) + preds.add(this.getSource(edge)); + + return Collections.unmodifiableCollection(preds); + } + + public Collection getSuccessors(V vertex) { + if (!containsVertex(vertex)) + return null; + + Set succs = new HashSet(); + for (E edge : getOutgoing_internal(vertex)) + succs.add(this.getDest(edge)); + + return Collections.unmodifiableCollection(succs); + } + + public Collection getNeighbors(V vertex) { + if (!containsVertex(vertex)) + return null; + + Collection neighbors = new HashSet(); + for (E edge : getIncoming_internal(vertex)) + neighbors.add(this.getSource(edge)); + for (E edge : getOutgoing_internal(vertex)) + neighbors.add(this.getDest(edge)); + return Collections.unmodifiableCollection(neighbors); + } + + public Collection getIncidentEdges(V vertex) { + if (!containsVertex(vertex)) + return null; + + Collection incident = new HashSet(); + incident.addAll(getIncoming_internal(vertex)); + incident.addAll(getOutgoing_internal(vertex)); + return incident; + } + + @Override + public E findEdge(V v1, V v2) { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + for (E edge : getOutgoing_internal(v1)) + if (this.getDest(edge).equals(v2)) + return edge; + + return null; + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) + { + this.validateEdgeType(edgeType); + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + edges.put(edge, new_endpoints); + + V source = new_endpoints.getFirst(); + V dest = new_endpoints.getSecond(); + + if (!containsVertex(source)) + this.addVertex(source); + + if (!containsVertex(dest)) + this.addVertex(dest); + + getIncoming_internal(dest).add(edge); + getOutgoing_internal(source).add(edge); + + return true; + } + + + public V getSource(E edge) { + if (!containsEdge(edge)) + return null; + return this.getEndpoints(edge).getFirst(); + } + + public V getDest(E edge) { + if (!containsEdge(edge)) + return null; + return this.getEndpoints(edge).getSecond(); + } + + public boolean isSource(V vertex, E edge) { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return vertex.equals(this.getEndpoints(edge).getFirst()); + } + + public boolean isDest(V vertex, E edge) { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return vertex.equals(this.getEndpoints(edge).getSecond()); + } + + public Pair getEndpoints(E edge) { + return edges.get(edge); + } + + public int getEdgeCount() { + return edges.size(); + } + + public int getVertexCount() { + return vertices.size(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedKAryTree.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedKAryTree.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedKAryTree.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedKAryTree.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,807 @@ +/* + * Created on May 8, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Tree in which each vertex has + * ≤ k children. The value of 'k' is specified by the constructor + * parameter. A specific child (edge) can be retrieved directly by specifying the + * index at which the child is located. By default, new (child) vertices + * are added at the lowest index available, if no index is specified. + * + */ +@SuppressWarnings("serial") +public class OrderedKAryTree extends AbstractTypedGraph implements Tree +{ + protected Map> edge_vpairs; + protected Map vertex_data; + protected int height; + protected V root; + protected int order; + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @param order the maximum number of children ("k") that any vertex can have + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory(final int order) { + return new Supplier> () { + public DirectedGraph get() { + return new OrderedKAryTree(order); + } + }; + } + + /** + * Creates a new instance with the specified order (maximum number of children). + * @param order the maximum number of children ("k") that any vertex can have + */ + public OrderedKAryTree(int order) + { + super(EdgeType.DIRECTED); + this.order = order; + this.height = -1; + this.edge_vpairs = new HashMap>(); + this.vertex_data = new HashMap(); + } + + /** + * @param vertex the vertex whose number of children is to be returned + * @return the number of children that {@code vertex} has + * @see edu.uci.ics.jung.graph.Tree#getChildCount(java.lang.Object) + */ + public int getChildCount(V vertex) { + if (!containsVertex(vertex)) + return 0; + List edges = vertex_data.get(vertex).child_edges; + if (edges == null) + return 0; + int count = 0; + for (E edge : edges) + count += edge == null ? 0 : 1; + + return count; + } + + /** + * @param vertex the vertex whose child edge is to be returned + * @param index the index of the edge to be returned + * @return the child edge of {@code vertex} at index {@code index}, that is, + * its ith child edge. + */ + public E getChildEdge(V vertex, int index) + { + if (!containsVertex(vertex)) + return null; + List edges = vertex_data.get(vertex).child_edges; + if (edges == null) + return null; + return edges.get(index); + } + + /** + * @see edu.uci.ics.jung.graph.Tree#getChildEdges(java.lang.Object) + */ + public Collection getChildEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + List edges = vertex_data.get(vertex).child_edges; + return edges == null ? Collections.emptySet() : + new ImmutableList.Builder().addAll(edges).build(); + } + + /** + * Returns an ordered list of {@code vertex}'s child vertices. + * If there is no child in position i, then the list will contain + * {@code null} in position i. If {@code vertex} has no children + * then the empty set will be returned. + * @see edu.uci.ics.jung.graph.Tree#getChildren(java.lang.Object) + */ + public Collection getChildren(V vertex) + { + if (!containsVertex(vertex)) + return null; + List edges = vertex_data.get(vertex).child_edges; + if (edges == null) + return Collections.emptySet(); + Collection children = new ArrayList(order); + for (E edge : edges) + children.add(this.getOpposite(vertex, edge)); + return new ImmutableList.Builder().addAll(children).build(); + } + + /** + * @see edu.uci.ics.jung.graph.Tree#getDepth(java.lang.Object) + * @return the depth of the vertex in this tree, or -1 if the vertex is + * not present in this tree + */ + public int getDepth(V vertex) + { + if (!containsVertex(vertex)) + return -1; + return vertex_data.get(vertex).depth; + } + + /** + * Returns the height of the tree, or -1 if the tree is empty. + * @see edu.uci.ics.jung.graph.Tree#getHeight() + */ + public int getHeight() + { + return height; + } + + /** + * @see edu.uci.ics.jung.graph.Tree#getParent(java.lang.Object) + */ + public V getParent(V vertex) + { + if (!containsVertex(vertex)) + return null; + else if (vertex.equals(root)) + return null; + return edge_vpairs.get(vertex_data.get(vertex).parent_edge).getFirst(); + } + + /** + * @see edu.uci.ics.jung.graph.Tree#getParentEdge(java.lang.Object) + */ + public E getParentEdge(V vertex) + { + if (!containsVertex(vertex)) + return null; + return vertex_data.get(vertex).parent_edge; + } + + /** + * @see edu.uci.ics.jung.graph.Tree#getRoot() + */ + public V getRoot() + { + return root; + } + + /** + * @see edu.uci.ics.jung.graph.Forest#getTrees() + */ + public Collection> getTrees() + { + Collection> forest = new ArrayList>(1); + forest.add(this); + return forest; + } + + /** + * Adds the specified {@code child} vertex and edge {@code e} to the graph + * with the specified parent vertex {@code parent}. If {@code index} is + * greater than or equal to 0, then the child is placed at position + * {@code index}; if it is less than 0, the child is placed at the lowest + * available position; if it is greater than or equal to the order of this + * tree, an exception is thrown. + * + * @param e the edge to add + * @param parent the source of the edge to be added + * @param child the destination of the edge to be added + * @param index the position at which e is to be added as a child of {@code parent} + * @return {@code true} if the graph has been modified + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object) + */ + public boolean addEdge(E e, V parent, V child, int index) + { + if (e == null || child == null || parent == null) + throw new IllegalArgumentException("Inputs may not be null"); + if (!containsVertex(parent)) + throw new IllegalArgumentException("Tree must already " + + "include parent: " + parent); + if (containsVertex(child)) + throw new IllegalArgumentException("Tree must not already " + + "include child: " + child); + if (parent.equals(child)) + throw new IllegalArgumentException("Input vertices must be distinct"); + if (index < 0 || index >= order) + throw new IllegalArgumentException("'index' must be in [0, [order-1]]"); + + Pair endpoints = new Pair(parent, child); + if (containsEdge(e)) + if (!endpoints.equals(edge_vpairs.get(e))) + throw new IllegalArgumentException("Tree already includes edge" + + e + " with different endpoints " + edge_vpairs.get(e)); + else + return false; + + VertexData parent_data = vertex_data.get(parent); + List outedges = parent_data.child_edges; + + if (outedges == null) + outedges = new ArrayList(this.order); + + boolean edge_placed = false; + if (index >= 0) + if (outedges.get(index) != null) + throw new IllegalArgumentException("Parent " + parent + + " already has a child at index " + index + " in this tree"); + else + outedges.set(index, e); + for (int i = 0; i < order; i++) + { + if (outedges.get(i) == null) + { + outedges.set(i, e); + edge_placed = true; + break; + } + } + if (!edge_placed) + throw new IllegalArgumentException("Parent " + parent + " already" + + " has " + order + " children in this tree"); + + // initialize VertexData for child; leave child's child_edges null for now + VertexData child_data = new VertexData(e, parent_data.depth + 1); + vertex_data.put(child, child_data); + + height = child_data.depth > height ? child_data.depth : height; + edge_vpairs.put(e, endpoints); + + return true; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object) + */ + @Override + public boolean addEdge(E e, V parent, V child) + { + return addEdge(e, parent, child, -1); + } + + + /** + * @see edu.uci.ics.jung.graph.Graph#addEdge(java.lang.Object, java.lang.Object, java.lang.Object, edu.uci.ics.jung.graph.util.EdgeType) + */ + @Override + public boolean addEdge(E e, V v1, V v2, EdgeType edge_type) + { + this.validateEdgeType(edge_type); + return addEdge(e, v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getDest(java.lang.Object) + */ + public V getDest(E directed_edge) + { + if (!containsEdge(directed_edge)) + return null; + return edge_vpairs.get(directed_edge).getSecond(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getEndpoints(java.lang.Object) + */ + public Pair getEndpoints(E edge) + { + if (!containsEdge(edge)) + return null; + return edge_vpairs.get(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getInEdges(java.lang.Object) + */ + public Collection getInEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + else if (vertex.equals(root)) + return Collections.emptySet(); + else + return Collections.singleton(getParentEdge(vertex)); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOpposite(java.lang.Object, java.lang.Object) + */ + @Override + public V getOpposite(V vertex, E edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + return null; + Pair endpoints = edge_vpairs.get(edge); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + return v1.equals(vertex) ? v2 : v1; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getOutEdges(java.lang.Object) + */ + public Collection getOutEdges(V vertex) + { + return getChildEdges(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessorCount(java.lang.Object) + * @return 0 if vertex is the root, -1 if the vertex is + * not an element of this tree, and 1 otherwise + */ + @Override + public int getPredecessorCount(V vertex) + { + if (!containsVertex(vertex)) + return -1; + return vertex.equals(root) ? 0 : 1; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getPredecessors(java.lang.Object) + */ + public Collection getPredecessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + if (vertex.equals(root)) + return Collections.emptySet(); + return Collections.singleton(getParent(vertex)); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSource(java.lang.Object) + */ + public V getSource(E directed_edge) + { + if (!containsEdge(directed_edge)) + return null; + return edge_vpairs.get(directed_edge).getFirst(); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessorCount(java.lang.Object) + */ + @Override + public int getSuccessorCount(V vertex) + { + return getChildCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#getSuccessors(java.lang.Object) + */ + public Collection getSuccessors(V vertex) + { + return getChildren(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#inDegree(java.lang.Object) + */ + @Override + public int inDegree(V vertex) + { + if (!containsVertex(vertex)) + return 0; + if (vertex.equals(root)) + return 0; + return 1; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isDest(java.lang.Object, java.lang.Object) + */ + public boolean isDest(V vertex, E edge) + { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return edge_vpairs.get(edge).getSecond().equals(vertex); + } + + /** + * Returns true if vertex is a leaf of this tree, + * i.e., if it has no children. + * @param vertex the vertex to be queried + * @return true if outDegree(vertex)==0 + */ + public boolean isLeaf(V vertex) + { + if (!containsVertex(vertex)) + return false; + return outDegree(vertex) == 0; + } + + /** + * Returns true iff v1 is the parent of v2. + * Note that if v2 is the root and v1 is null, + * this method returns true. + * + * @see edu.uci.ics.jung.graph.Graph#isPredecessor(java.lang.Object, java.lang.Object) + */ + @Override + public boolean isPredecessor(V v1, V v2) + { + if (!containsVertex(v2)) + return false; + return getParent(v2).equals(v1); + } + + /** + * Returns true if vertex is a leaf of this tree, + * i.e., if it has no children. + * @param vertex the vertex to be queried + * @return true if outDegree(vertex)==0 + */ + public boolean isRoot(V vertex) + { + if (root == null) + return false; + return root.equals(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSource(java.lang.Object, java.lang.Object) + */ + public boolean isSource(V vertex, E edge) + { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return edge_vpairs.get(edge).getFirst().equals(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Graph#isSuccessor(java.lang.Object, java.lang.Object) + */ + @Override + public boolean isSuccessor(V v1, V v2) + { + if (!containsVertex(v2)) + return false; + if (containsVertex(v1)) + return getParent(v1).equals(v2); + return isLeaf(v2) && v1 == null; + } + + /** + * @see edu.uci.ics.jung.graph.Graph#outDegree(java.lang.Object) + */ + @Override + public int outDegree(V vertex) + { + if (!containsVertex(vertex)) + return 0; + List out_edges = vertex_data.get(vertex).child_edges; + if (out_edges == null) + return 0; + int degree = 0; + for (E e : out_edges) + degree += (e == null) ? 0 : 1; + return degree; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addEdge(java.lang.Object, java.util.Collection) + */ + @Override + @SuppressWarnings("unchecked") + public boolean addEdge(E edge, Collection vertices, EdgeType edge_type) + { + if (edge == null || vertices == null) + throw new IllegalArgumentException("inputs may not be null"); + if (vertices.size() != 2) + throw new IllegalArgumentException("'vertices' must contain " + + "exactly 2 distinct vertices"); + this.validateEdgeType(edge_type); + Pair endpoints; + if (vertices instanceof Pair) + endpoints = (Pair)vertices; + else + endpoints = new Pair(vertices); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + if (v1.equals(v2)) + throw new IllegalArgumentException("Input vertices must be distinct"); + return addEdge(edge, v1, v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#addVertex(java.lang.Object) + */ + public boolean addVertex(V vertex) + { + if(root == null) + { + this.root = vertex; + vertex_data.put(vertex, new VertexData(null, 0)); + this.height = 0; + return true; + } + else + { + throw new UnsupportedOperationException("Unless you are setting " + + "the root, use addEdge() or addChild()"); + } + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isIncident(java.lang.Object, java.lang.Object) + */ + @Override + public boolean isIncident(V vertex, E edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + return false; + return edge_vpairs.get(edge).contains(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#isNeighbor(java.lang.Object, java.lang.Object) + */ + @Override + public boolean isNeighbor(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return false; + return getNeighbors(v1).contains(v2); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsEdge(java.lang.Object) + */ + public boolean containsEdge(E edge) + { + return edge_vpairs.containsKey(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#containsVertex(java.lang.Object) + */ + public boolean containsVertex(V vertex) + { + return vertex_data.containsKey(vertex); + } + + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdge(java.lang.Object, java.lang.Object) + */ + @Override + public E findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + VertexData v1_data = vertex_data.get(v1); + if (edge_vpairs.get(v1_data.parent_edge).getFirst().equals(v2)) + return v1_data.parent_edge; + List edges = v1_data.child_edges; + if (edges == null) + return null; + for (E edge : edges) + if (edge != null && edge_vpairs.get(edge).getSecond().equals(v2)) + return edge; + return null; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#findEdgeSet(java.lang.Object, java.lang.Object) + */ + @Override + public Collection findEdgeSet(V v1, V v2) + { + E edge = findEdge(v1, v2); + if (edge == null) + return Collections.emptySet(); + else + return Collections.singleton(edge); + } + + /** + * Returns the child of vertex at position index + * in this tree, or null if it has no child at that position. + * @param vertex the vertex to query + * @param index the index of the child to return + * @return the child of vertex at position index + * in this tree, or null if it has no child at that position + * @throws ArrayIndexOutOfBoundsException if index is not in + * the range {@code [0, order-1]} + */ + public V getChild(V vertex, int index) + { + if (index < 0 || index >= order) + throw new ArrayIndexOutOfBoundsException(index + " is not in [0, order-1]"); + if (!containsVertex(vertex)) + return null; + List edges = vertex_data.get(vertex).child_edges; + if (edges == null) + return null; + E edge = edges.get(index); + return edge == null ? null : edge_vpairs.get(edge).getSecond(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdgeCount() + */ + public int getEdgeCount() + { + return edge_vpairs.size(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getEdges() + */ + public Collection getEdges() + { + return new ImmutableSet.Builder().addAll(edge_vpairs.keySet()).build(); + //CollectionUtils.unmodifiableCollection(edge_vpairs.keySet()); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentCount(java.lang.Object) + */ + @Override + public int getIncidentCount(E edge) + { + return 2; // all tree edges have 2 incident vertices + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentEdges(java.lang.Object) + */ + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + ArrayList edges = new ArrayList(order+1); + VertexData v_data = vertex_data.get(vertex); + if (v_data.parent_edge != null) + edges.add(v_data.parent_edge); + if (v_data.child_edges != null) + { + for (E edge : v_data.child_edges) + if (edge != null) + edges.add(edge); + } + if (edges.isEmpty()) + return Collections.emptySet(); + return Collections.unmodifiableCollection(edges); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getIncidentVertices(java.lang.Object) + */ + @Override + public Collection getIncidentVertices(E edge) + { + return edge_vpairs.get(edge); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighborCount(java.lang.Object) + */ + @Override + public int getNeighborCount(V vertex) + { + if (!containsVertex(vertex)) + return 0; + return (vertex.equals(root) ? 0 : 1) + this.getChildCount(vertex); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getNeighbors(java.lang.Object) + */ + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + ArrayList vertices = new ArrayList(order+1); + VertexData v_data = vertex_data.get(vertex); + if (v_data.parent_edge != null) + vertices.add(edge_vpairs.get(v_data.parent_edge).getFirst()); + if (v_data.child_edges != null) + { + for (E edge : v_data.child_edges) + if (edge != null) + vertices.add(edge_vpairs.get(edge).getSecond()); + } + if (vertices.isEmpty()) + return Collections.emptySet(); + return Collections.unmodifiableCollection(vertices); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertexCount() + */ + public int getVertexCount() + { + return vertex_data.size(); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#getVertices() + */ + public Collection getVertices() + { + return new ImmutableSet.Builder().addAll(vertex_data.keySet()).build(); + //CollectionUtils.unmodifiableCollection(vertex_data.keySet()); + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeEdge(java.lang.Object) + */ + public boolean removeEdge(E edge) + { + if (!containsEdge(edge)) + return false; + + removeVertex(edge_vpairs.get(edge).getSecond()); + edge_vpairs.remove(edge); + + return true; + } + + /** + * @see edu.uci.ics.jung.graph.Hypergraph#removeVertex(java.lang.Object) + */ + public boolean removeVertex(V vertex) + { + if (!containsVertex(vertex)) + return false; + + // recursively remove all of vertex's children + for(V v : getChildren(vertex)) + removeVertex(v); + + E parent_edge = getParentEdge(vertex); + edge_vpairs.remove(parent_edge); + List edges = vertex_data.get(vertex).child_edges; + if (edges != null) + for (E edge : edges) + edge_vpairs.remove(edge); + vertex_data.remove(vertex); + + return true; + } + + protected class VertexData + { + List child_edges; + E parent_edge; + int depth; + + protected VertexData(E parent_edge, int depth) + { + this.parent_edge = parent_edge; + this.depth = depth; + } + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) + { + if (edge == null || endpoints == null) + throw new IllegalArgumentException("inputs must not be null"); + return addEdge(edge, endpoints.getFirst(), endpoints.getSecond(), edgeType); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/OrderedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * Created on Oct 18, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Graph that orders its vertex and edge collections + * according to insertion time, is suitable for sparse graphs, and + * permits directed, undirected, and parallel edges. + */ +@SuppressWarnings("serial") +public class OrderedSparseMultigraph + extends SparseMultigraph + implements MultiGraph { + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + public Graph get() { + return new OrderedSparseMultigraph(); + } + }; + } + + /** + * Creates a new instance. + */ + public OrderedSparseMultigraph() + { + vertices = new LinkedHashMap>>(); + edges = new LinkedHashMap>(); + directedEdges = new LinkedHashSet(); + } + + @Override + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertices.put(vertex, new Pair>(new LinkedHashSet(), new LinkedHashSet())); + return true; + } else { + return false; + } + } + + + @Override + public Collection getPredecessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Set preds = new LinkedHashSet(); + for (E edge : getIncoming_internal(vertex)) { + if(getEdgeType(edge) == EdgeType.DIRECTED) { + preds.add(this.getSource(edge)); + } else { + preds.add(getOpposite(vertex, edge)); + } + } + return Collections.unmodifiableCollection(preds); + } + + @Override + public Collection getSuccessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Set succs = new LinkedHashSet(); + for (E edge : getOutgoing_internal(vertex)) { + if(getEdgeType(edge) == EdgeType.DIRECTED) { + succs.add(this.getDest(edge)); + } else { + succs.add(getOpposite(vertex, edge)); + } + } + return Collections.unmodifiableCollection(succs); + } + + @Override + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Collection out = new LinkedHashSet(); + out.addAll(this.getPredecessors(vertex)); + out.addAll(this.getSuccessors(vertex)); + return out; + } + + @Override + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Collection out = new LinkedHashSet(); + out.addAll(this.getInEdges(vertex)); + out.addAll(this.getOutEdges(vertex)); + return out; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SetHypergraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SetHypergraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SetHypergraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SetHypergraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,344 @@ +/* + * Created on Feb 4, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; + +/** + * An implementation of Hypergraph that is suitable for sparse graphs and + * permits parallel edges. + */ +@SuppressWarnings("serial") +public class SetHypergraph + implements Hypergraph, MultiGraph, Serializable +{ + protected Map> vertices; // Map of vertices to incident hyperedge sets + protected Map> edges; // Map of hyperedges to incident vertex sets + + /** + * Returns a Factory which creates instances of this class. + * @param vertex type of the hypergraph to be created + * @param edge type of the hypergraph to be created + * @return a Factory which creates instances of this class + */ + public static Supplier> getFactory() { + return new Supplier> () { + public Hypergraph get() { + return new SetHypergraph(); + } + }; + } + + /** + * Creates a SetHypergraph and initializes the internal data structures. + */ + public SetHypergraph() + { + vertices = new HashMap>(); + edges = new HashMap>(); + } + + /** + * Adds hyperedge to this graph and connects them to the vertex collection to_attach. + * Any vertices in to_attach that appear more than once will only appear once in the + * incident vertex collection for hyperedge, that is, duplicates will be ignored. + * + * @see Hypergraph#addEdge(Object, Collection) + */ + public boolean addEdge(H hyperedge, Collection to_attach) + { + if (hyperedge == null) + throw new IllegalArgumentException("input hyperedge may not be null"); + + if (to_attach == null) + throw new IllegalArgumentException("endpoints may not be null"); + + if(to_attach.contains(null)) + throw new IllegalArgumentException("cannot add an edge with a null endpoint"); + + Set new_endpoints = new HashSet(to_attach); + if (edges.containsKey(hyperedge)) + { + Collection attached = edges.get(hyperedge); + if (!attached.equals(new_endpoints)) + { + throw new IllegalArgumentException("Edge " + hyperedge + + " exists in this graph with endpoints " + attached); + } + else + return false; + } + edges.put(hyperedge, new_endpoints); + for (V v : to_attach) + { + // add v if it's not already in the graph + addVertex(v); + + // associate v with hyperedge + vertices.get(v).add(hyperedge); + } + return true; + } + + /** + * @see Hypergraph#addEdge(Object, Collection, EdgeType) + */ + public boolean addEdge(H hyperedge, Collection to_attach, + EdgeType edge_type) + { + if (edge_type != EdgeType.UNDIRECTED) + throw new IllegalArgumentException("Edge type for this " + + "implementation must be EdgeType.HYPER, not " + + edge_type); + return addEdge(hyperedge, to_attach); + } + + /** + * @see Hypergraph#getEdgeType(Object) + */ + public EdgeType getEdgeType(H edge) + { + if (containsEdge(edge)) + return EdgeType.UNDIRECTED; + else + return null; + } + + public boolean containsVertex(V vertex) { + return vertices.keySet().contains(vertex); + } + + public boolean containsEdge(H edge) { + return edges.keySet().contains(edge); + } + + public Collection getEdges() + { + return edges.keySet(); + } + + public Collection getVertices() + { + return vertices.keySet(); + } + + public int getEdgeCount() + { + return edges.size(); + } + + public int getVertexCount() + { + return vertices.size(); + } + + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Set neighbors = new HashSet(); + for (H hyperedge : vertices.get(vertex)) + { + neighbors.addAll(edges.get(hyperedge)); + } + return neighbors; + } + + public Collection getIncidentEdges(V vertex) + { + return vertices.get(vertex); + } + + public Collection getIncidentVertices(H edge) + { + return edges.get(edge); + } + + public H findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + + for (H h : getIncidentEdges(v1)) + { + if (isIncident(v2, h)) + return h; + } + return null; + } + + public Collection findEdgeSet(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + + Collection edges = new ArrayList(); + for (H h : getIncidentEdges(v1)) + { + if (isIncident(v2, h)) + edges.add(h); + } + return Collections.unmodifiableCollection(edges); + } + + public boolean addVertex(V vertex) + { + if(vertex == null) + throw new IllegalArgumentException("cannot add a null vertex"); + if (containsVertex(vertex)) + return false; + vertices.put(vertex, new HashSet()); + return true; + } + + public boolean removeVertex(V vertex) + { + if (!containsVertex(vertex)) + return false; + for (H hyperedge : vertices.get(vertex)) + { + edges.get(hyperedge).remove(vertex); + } + vertices.remove(vertex); + return true; + } + + public boolean removeEdge(H hyperedge) + { + if (!containsEdge(hyperedge)) + return false; + for (V vertex : edges.get(hyperedge)) + { + vertices.get(vertex).remove(hyperedge); + } + edges.remove(hyperedge); + return true; + } + + public boolean isNeighbor(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return false; + + if (vertices.get(v2).isEmpty()) + return false; + for (H hyperedge : vertices.get(v1)) + { + if (edges.get(hyperedge).contains(v2)) + return true; + } + return false; + } + + public boolean isIncident(V vertex, H edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + return false; + + return vertices.get(vertex).contains(edge); + } + + public int degree(V vertex) + { + if (!containsVertex(vertex)) + return 0; + + return vertices.get(vertex).size(); + } + + public int getNeighborCount(V vertex) + { + if (!containsVertex(vertex)) + return 0; + + return getNeighbors(vertex).size(); + } + + public int getIncidentCount(H edge) + { + if (!containsEdge(edge)) + return 0; + + return edges.get(edge).size(); + } + + public int getEdgeCount(EdgeType edge_type) + { + if (edge_type == EdgeType.UNDIRECTED) + return edges.size(); + return 0; + } + + public Collection getEdges(EdgeType edge_type) + { + if (edge_type == EdgeType.UNDIRECTED) + return edges.keySet(); + return null; + } + + public EdgeType getDefaultEdgeType() + { + return EdgeType.UNDIRECTED; + } + + public Collection getInEdges(V vertex) + { + return getIncidentEdges(vertex); + } + + public Collection getOutEdges(V vertex) + { + return getIncidentEdges(vertex); + } + + public int inDegree(V vertex) + { + return degree(vertex); + } + + public int outDegree(V vertex) + { + return degree(vertex); + } + + public V getDest(H directed_edge) + { + return null; + } + + public V getSource(H directed_edge) + { + return null; + } + + public Collection getPredecessors(V vertex) + { + return getNeighbors(vertex); + } + + public Collection getSuccessors(V vertex) + { + return getNeighbors(vertex); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SortedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SortedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SortedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SortedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,128 @@ +/* + * Created on Oct 18, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Comparator; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + +import com.google.common.base.Supplier; +import com.google.common.collect.Ordering; + +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Graph that is suitable for sparse graphs, + * orders its vertex and edge collections according to either specified Comparator + * instances or the natural ordering of their elements, and permits directed, undirected, + * and parallel edges. + * + * @author Joshua O'Madadhain + */ +@SuppressWarnings("serial") +public class SortedSparseMultigraph + extends OrderedSparseMultigraph + implements MultiGraph +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() + { + return new Supplier> () + { + public Graph get() + { + return new SortedSparseMultigraph(); + } + }; + } + + /** + * Comparator used in ordering vertices. Defaults to util.ComparableComparator + * if no comparators are specified in the constructor. + */ + protected Comparator vertex_comparator; + + /** + * Comparator used in ordering edges. Defaults to util.ComparableComparator + * if no comparators are specified in the constructor. + */ + protected Comparator edge_comparator; + + /** + * Creates a new instance which sorts its vertices and edges according to the + * specified {@code Comparator}s. + * @param vertex_comparator specifies how the vertices are to be compared + * @param edge_comparator specifies how the edges are to be compared + */ + public SortedSparseMultigraph(Comparator vertex_comparator, Comparator edge_comparator) + { + this.vertex_comparator = vertex_comparator; + this.edge_comparator = edge_comparator; + vertices = new TreeMap>>(vertex_comparator); + edges = new TreeMap>(edge_comparator); + directedEdges = new TreeSet(edge_comparator); + } + + /** + * Creates a new instance which sorts its vertices and edges according to + * their natural ordering. + */ + public SortedSparseMultigraph() + { + this(new Ordering(){ + @SuppressWarnings("unchecked") + public int compare(V v1, V v2) { + return ((Comparable) v1).compareTo(v2); + }}, + new Ordering(){ + @SuppressWarnings("unchecked") + public int compare(E e1, E e2) { + return ((Comparable) e1).compareTo(e2); + }}); + } + + /** + * Provides a new {@code Comparator} to be used in sorting the vertices. + * @param vertex_comparator the comparator that defines the new ordering + */ + public void setVertexComparator(Comparator vertex_comparator) + { + this.vertex_comparator = vertex_comparator; + Map>> tmp_vertices = new TreeMap>>(vertex_comparator); + for (Map.Entry>> entry : vertices.entrySet()) + tmp_vertices.put(entry.getKey(), entry.getValue()); + this.vertices = tmp_vertices; + } + + @Override + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) + { + vertices.put(vertex, new Pair>(new TreeSet(edge_comparator), + new TreeSet(edge_comparator))); + return true; + } + else + { + return false; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseGraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseGraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,373 @@ +/* + * Created on Apr 15, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Graph that is suitable for sparse graphs and + * permits both directed and undirected edges. + */ +@SuppressWarnings("serial") +public class SparseGraph + extends AbstractGraph + implements Graph +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() + { + return new Supplier> () + { + public Graph get() + { + return new SparseGraph(); + } + }; + } + + protected static final int INCOMING = 0; + protected static final int OUTGOING = 1; + protected static final int INCIDENT = 2; + + protected Map[]> vertex_maps; // Map of vertices to adjacency maps of vertices to {incoming, outgoing, incident} edges + protected Map> directed_edges; // Map of directed edges to incident vertex sets + protected Map> undirected_edges; // Map of undirected edges to incident vertex sets + + /** + * Creates an instance. + */ + public SparseGraph() + { + vertex_maps = new HashMap[]>(); + directed_edges = new HashMap>(); + undirected_edges = new HashMap>(); + } + + @Override + public E findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + E edge = vertex_maps.get(v1)[OUTGOING].get(v2); + if (edge == null) + edge = vertex_maps.get(v1)[INCIDENT].get(v2); + return edge; + } + + @Override + public Collection findEdgeSet(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + Collection edges = new ArrayList(2); + E e1 = vertex_maps.get(v1)[OUTGOING].get(v2); + if (e1 != null) + edges.add(e1); + E e2 = vertex_maps.get(v1)[INCIDENT].get(v2); + if (e1 != null) + edges.add(e2); + return edges; + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) + { + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + V v1 = new_endpoints.getFirst(); + V v2 = new_endpoints.getSecond(); + + // undirected edges and directed edges are not considered to be parallel to each other, + // so as long as anything that's returned by findEdge is not of the same type as + // edge, we're fine + E connection = findEdge(v1, v2); + if (connection != null && getEdgeType(connection) == edgeType) + return false; + + if (!containsVertex(v1)) + this.addVertex(v1); + + if (!containsVertex(v2)) + this.addVertex(v2); + + // map v1 to and vice versa + if (edgeType == EdgeType.DIRECTED) + { + vertex_maps.get(v1)[OUTGOING].put(v2, edge); + vertex_maps.get(v2)[INCOMING].put(v1, edge); + directed_edges.put(edge, new_endpoints); + } + else + { + vertex_maps.get(v1)[INCIDENT].put(v2, edge); + vertex_maps.get(v2)[INCIDENT].put(v1, edge); + undirected_edges.put(edge, new_endpoints); + } + + return true; + } + + + + public Collection getInEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + + // combine directed inedges and undirected + Collection in = new HashSet(vertex_maps.get(vertex)[INCOMING].values()); + in.addAll(vertex_maps.get(vertex)[INCIDENT].values()); + return Collections.unmodifiableCollection(in); + } + + public Collection getOutEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + + // combine directed outedges and undirected + Collection out = new HashSet(vertex_maps.get(vertex)[OUTGOING].values()); + out.addAll(vertex_maps.get(vertex)[INCIDENT].values()); + return Collections.unmodifiableCollection(out); + } + + public Collection getPredecessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + // consider directed inedges and undirected + Collection preds = new HashSet(vertex_maps.get(vertex)[INCOMING].keySet()); + preds.addAll(vertex_maps.get(vertex)[INCIDENT].keySet()); + return Collections.unmodifiableCollection(preds); + } + + public Collection getSuccessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + // consider directed outedges and undirected + Collection succs = new HashSet(vertex_maps.get(vertex)[OUTGOING].keySet()); + succs.addAll(vertex_maps.get(vertex)[INCIDENT].keySet()); + return Collections.unmodifiableCollection(succs); + } + + public Collection getEdges(EdgeType edgeType) + { + if (edgeType == EdgeType.DIRECTED) + return Collections.unmodifiableCollection(directed_edges.keySet()); + else if (edgeType == EdgeType.UNDIRECTED) + return Collections.unmodifiableCollection(undirected_edges.keySet()); + else + return null; + } + + public Pair getEndpoints(E edge) + { + Pair endpoints; + endpoints = directed_edges.get(edge); + if (endpoints == null) + return undirected_edges.get(edge); + else + return endpoints; + } + + public EdgeType getEdgeType(E edge) + { + if (directed_edges.containsKey(edge)) + return EdgeType.DIRECTED; + else if (undirected_edges.containsKey(edge)) + return EdgeType.UNDIRECTED; + else + return null; + } + + public V getSource(E directed_edge) + { + if (getEdgeType(directed_edge) == EdgeType.DIRECTED) + return directed_edges.get(directed_edge).getFirst(); + else + return null; + } + + public V getDest(E directed_edge) + { + if (getEdgeType(directed_edge) == EdgeType.DIRECTED) + return directed_edges.get(directed_edge).getSecond(); + else + return null; + } + + public boolean isSource(V vertex, E edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + return false; + + V source = getSource(edge); + if (source != null) + return source.equals(vertex); + else + return false; + } + + public boolean isDest(V vertex, E edge) + { + if (!containsVertex(vertex) || !containsEdge(edge)) + return false; + + V dest = getDest(edge); + if (dest != null) + return dest.equals(vertex); + else + return false; + } + + public Collection getEdges() + { + Collection edges = new ArrayList(directed_edges.keySet()); + edges.addAll(undirected_edges.keySet()); + return Collections.unmodifiableCollection(edges); + } + + public Collection getVertices() + { + return Collections.unmodifiableCollection(vertex_maps.keySet()); + } + + public boolean containsVertex(V vertex) + { + return vertex_maps.containsKey(vertex); + } + + public boolean containsEdge(E edge) + { + return directed_edges.containsKey(edge) || undirected_edges.containsKey(edge); + } + + public int getEdgeCount() + { + return directed_edges.size() + undirected_edges.size(); + } + + public int getVertexCount() + { + return vertex_maps.size(); + } + + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + // consider directed edges and undirected edges + Collection neighbors = new HashSet(vertex_maps.get(vertex)[INCOMING].keySet()); + neighbors.addAll(vertex_maps.get(vertex)[OUTGOING].keySet()); + neighbors.addAll(vertex_maps.get(vertex)[INCIDENT].keySet()); + return Collections.unmodifiableCollection(neighbors); + } + + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + Collection incident = new HashSet(vertex_maps.get(vertex)[INCOMING].values()); + incident.addAll(vertex_maps.get(vertex)[OUTGOING].values()); + incident.addAll(vertex_maps.get(vertex)[INCIDENT].values()); + return Collections.unmodifiableCollection(incident); + } + + @SuppressWarnings("unchecked") + public boolean addVertex(V vertex) + { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertex_maps.put(vertex, new HashMap[]{new HashMap(), new HashMap(), new HashMap()}); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) + { + if (!containsVertex(vertex)) + return false; + + // copy to avoid concurrent modification in removeEdge + Collection incident = new ArrayList(getIncidentEdges(vertex)); + + for (E edge : incident) + removeEdge(edge); + + vertex_maps.remove(vertex); + + return true; + } + + public boolean removeEdge(E edge) + { + if (!containsEdge(edge)) + return false; + + Pair endpoints = getEndpoints(edge); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + // remove edge from incident vertices' adjacency maps + if (getEdgeType(edge) == EdgeType.DIRECTED) + { + vertex_maps.get(v1)[OUTGOING].remove(v2); + vertex_maps.get(v2)[INCOMING].remove(v1); + directed_edges.remove(edge); + } + else + { + vertex_maps.get(v1)[INCIDENT].remove(v2); + vertex_maps.get(v2)[INCIDENT].remove(v1); + undirected_edges.remove(edge); + } + + return true; + } + + public int getEdgeCount(EdgeType edge_type) + { + if (edge_type == EdgeType.DIRECTED) + return directed_edges.size(); + if (edge_type == EdgeType.UNDIRECTED) + return undirected_edges.size(); + return 0; + } + + public EdgeType getDefaultEdgeType() + { + return EdgeType.UNDIRECTED; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/SparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,320 @@ +/* + * Created on Oct 18, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of Graph that is suitable for sparse graphs + * and permits directed, undirected, and parallel edges. + */ +@SuppressWarnings("serial") +public class SparseMultigraph + extends AbstractGraph + implements MultiGraph { + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type + */ + public static Supplier> getFactory() { + return new Supplier> () { + public Graph get() { + return new SparseMultigraph(); + } + }; + } + + // TODO: refactor internal representation: right now directed edges each have two references (in vertices and directedEdges) + // and undirected also have two (incoming and outgoing). + protected Map>> vertices; // Map of vertices to Pair of adjacency sets {incoming, outgoing} + protected Map> edges; // Map of edges to incident vertex pairs + protected Set directedEdges; + + /** + * Creates a new instance. + */ + public SparseMultigraph() + { + vertices = new HashMap>>(); + edges = new HashMap>(); + directedEdges = new HashSet(); + } + + public Collection getEdges() + { + return Collections.unmodifiableCollection(edges.keySet()); + } + + public Collection getVertices() + { + return Collections.unmodifiableCollection(vertices.keySet()); + } + + public boolean containsVertex(V vertex) { + return vertices.keySet().contains(vertex); + } + + public boolean containsEdge(E edge) { + return edges.keySet().contains(edge); + } + + protected Collection getIncoming_internal(V vertex) + { + return vertices.get(vertex).getFirst(); + } + + protected Collection getOutgoing_internal(V vertex) + { + return vertices.get(vertex).getSecond(); + } + + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!vertices.containsKey(vertex)) { + vertices.put(vertex, new Pair>(new HashSet(), new HashSet())); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) { + if (!containsVertex(vertex)) + return false; + + // copy to avoid concurrent modification in removeEdge + Set incident = new HashSet(getIncoming_internal(vertex)); + incident.addAll(getOutgoing_internal(vertex)); + + for (E edge : incident) + removeEdge(edge); + + vertices.remove(vertex); + + return true; + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) { + + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + V v1 = new_endpoints.getFirst(); + V v2 = new_endpoints.getSecond(); + + if (!vertices.containsKey(v1)) + this.addVertex(v1); + + if (!vertices.containsKey(v2)) + this.addVertex(v2); + + + vertices.get(v1).getSecond().add(edge); + vertices.get(v2).getFirst().add(edge); + edges.put(edge, new_endpoints); + if(edgeType == EdgeType.DIRECTED) { + directedEdges.add(edge); + } else { + vertices.get(v1).getFirst().add(edge); + vertices.get(v2).getSecond().add(edge); + } + return true; + } + + public boolean removeEdge(E edge) + { + if (!containsEdge(edge)) { + return false; + } + + Pair endpoints = getEndpoints(edge); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + // remove edge from incident vertices' adjacency sets + vertices.get(v1).getSecond().remove(edge); + vertices.get(v2).getFirst().remove(edge); + + if(directedEdges.remove(edge) == false) { + + // its an undirected edge, remove the other ends + vertices.get(v2).getSecond().remove(edge); + vertices.get(v1).getFirst().remove(edge); + } + edges.remove(edge); + return true; + } + + public Collection getInEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(vertices.get(vertex).getFirst()); + } + + public Collection getOutEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(vertices.get(vertex).getSecond()); + } + + // TODO: this will need to get changed if we modify the internal representation + public Collection getPredecessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + + Set preds = new HashSet(); + for (E edge : getIncoming_internal(vertex)) { + if(getEdgeType(edge) == EdgeType.DIRECTED) { + preds.add(this.getSource(edge)); + } else { + preds.add(getOpposite(vertex, edge)); + } + } + return Collections.unmodifiableCollection(preds); + } + + // TODO: this will need to get changed if we modify the internal representation + public Collection getSuccessors(V vertex) + { + if (!containsVertex(vertex)) + return null; + Set succs = new HashSet(); + for (E edge : getOutgoing_internal(vertex)) { + if(getEdgeType(edge) == EdgeType.DIRECTED) { + succs.add(this.getDest(edge)); + } else { + succs.add(getOpposite(vertex, edge)); + } + } + return Collections.unmodifiableCollection(succs); + } + + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + Collection out = new HashSet(); + out.addAll(this.getPredecessors(vertex)); + out.addAll(this.getSuccessors(vertex)); + return out; + } + + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + Collection out = new HashSet(); + out.addAll(this.getInEdges(vertex)); + out.addAll(this.getOutEdges(vertex)); + return out; + } + + @Override + public E findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + for (E edge : getOutgoing_internal(v1)) + if (this.getOpposite(v1, edge).equals(v2)) + return edge; + + return null; + } + + public Pair getEndpoints(E edge) + { + return edges.get(edge); + } + + public V getSource(E edge) { + if(directedEdges.contains(edge)) { + return this.getEndpoints(edge).getFirst(); + } + return null; + } + + public V getDest(E edge) { + if(directedEdges.contains(edge)) { + return this.getEndpoints(edge).getSecond(); + } + return null; + } + + public boolean isSource(V vertex, E edge) { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return getSource(edge).equals(vertex); + } + + public boolean isDest(V vertex, E edge) { + if (!containsEdge(edge) || !containsVertex(vertex)) + return false; + return getDest(edge).equals(vertex); + } + + public EdgeType getEdgeType(E edge) { + return directedEdges.contains(edge) ? + EdgeType.DIRECTED : + EdgeType.UNDIRECTED; + } + + @SuppressWarnings("unchecked") + public Collection getEdges(EdgeType edgeType) { + if(edgeType == EdgeType.DIRECTED) { + return Collections.unmodifiableSet(this.directedEdges); + } else if(edgeType == EdgeType.UNDIRECTED) { + Collection edges = new HashSet(getEdges()); + edges.removeAll(directedEdges); + return edges; + } else { + return Collections.EMPTY_SET; + } + + } + + public int getEdgeCount() { + return edges.keySet().size(); + } + + public int getVertexCount() { + return vertices.keySet().size(); + } + + public int getEdgeCount(EdgeType edge_type) + { + return getEdges(edge_type).size(); + } + + public EdgeType getDefaultEdgeType() + { + return EdgeType.UNDIRECTED; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedOrderedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedOrderedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedOrderedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedOrderedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Created on Oct 18, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of UndirectedGraph that is suitable for sparse graphs, + * orders its vertex and edge collections according to insertion time, and permits + * parallel edges. + */ +@SuppressWarnings("serial") +public class UndirectedOrderedSparseMultigraph + extends UndirectedSparseMultigraph + implements UndirectedGraph { + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + public UndirectedGraph get() { + return new UndirectedOrderedSparseMultigraph(); + } + }; + } + + /** + * Creates a new instance. + */ + public UndirectedOrderedSparseMultigraph() { + vertices = new LinkedHashMap>(); + edges = new LinkedHashMap>(); + } + + @Override + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) + { + vertices.put(vertex, new LinkedHashSet()); + return true; + } else { + return false; + } + } + + @Override + public Collection getNeighbors(V vertex) { + if (!containsVertex(vertex)) + return null; + + Set neighbors = new LinkedHashSet(); + for (E edge : getIncident_internal(vertex)) + { + Pair endpoints = this.getEndpoints(edge); + V e_a = endpoints.getFirst(); + V e_b = endpoints.getSecond(); + if (vertex.equals(e_a)) + neighbors.add(e_b); + else + neighbors.add(e_a); + } + + return Collections.unmodifiableCollection(neighbors); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseGraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseGraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,243 @@ +/* + * Created on Apr 1, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of UndirectedGraph that is suitable + * for sparse graphs. + */ +@SuppressWarnings("serial") +public class UndirectedSparseGraph extends AbstractTypedGraph + implements UndirectedGraph +{ + + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + + public UndirectedGraph get() { + return new UndirectedSparseGraph(); + } + }; + } + + protected Map> vertices; // Map of vertices to adjacency maps of vertices to incident edges + protected Map> edges; // Map of edges to incident vertex sets + + /** + * Creates an instance. + */ + public UndirectedSparseGraph() { + super(EdgeType.UNDIRECTED); + vertices = new HashMap>(); + edges = new HashMap>(); + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edgeType) + { + this.validateEdgeType(edgeType); + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + V v1 = new_endpoints.getFirst(); + V v2 = new_endpoints.getSecond(); + + if (findEdge(v1, v2) != null) + return false; + + edges.put(edge, new_endpoints); + + if (!vertices.containsKey(v1)) + this.addVertex(v1); + + if (!vertices.containsKey(v2)) + this.addVertex(v2); + + // map v1 to and vice versa + vertices.get(v1).put(v2, edge); + vertices.get(v2).put(v1, edge); + + return true; + } + + public Collection getInEdges(V vertex) + { + return this.getIncidentEdges(vertex); + } + + public Collection getOutEdges(V vertex) + { + return this.getIncidentEdges(vertex); + } + + public Collection getPredecessors(V vertex) + { + return this.getNeighbors(vertex); + } + + public Collection getSuccessors(V vertex) + { + return this.getNeighbors(vertex); + } + + @Override + public E findEdge(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + return vertices.get(v1).get(v2); + } + + @Override + public Collection findEdgeSet(V v1, V v2) + { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + ArrayList edge_collection = new ArrayList(1); +// if (!containsVertex(v1) || !containsVertex(v2)) +// return edge_collection; + E e = findEdge(v1, v2); + if (e == null) + return edge_collection; + edge_collection.add(e); + return edge_collection; + } + + public Pair getEndpoints(E edge) + { + return edges.get(edge); + } + + public V getSource(E directed_edge) + { + return null; + } + + public V getDest(E directed_edge) + { + return null; + } + + public boolean isSource(V vertex, E edge) + { + return false; + } + + public boolean isDest(V vertex, E edge) + { + return false; + } + + public Collection getEdges() + { + return Collections.unmodifiableCollection(edges.keySet()); + } + + public Collection getVertices() + { + return Collections.unmodifiableCollection(vertices.keySet()); + } + + public boolean containsVertex(V vertex) + { + return vertices.containsKey(vertex); + } + + public boolean containsEdge(E edge) + { + return edges.containsKey(edge); + } + + public int getEdgeCount() + { + return edges.size(); + } + + public int getVertexCount() + { + return vertices.size(); + } + + public Collection getNeighbors(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(vertices.get(vertex).keySet()); + } + + public Collection getIncidentEdges(V vertex) + { + if (!containsVertex(vertex)) + return null; + return Collections.unmodifiableCollection(vertices.get(vertex).values()); + } + + public boolean addVertex(V vertex) + { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) { + vertices.put(vertex, new HashMap()); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) + { + if (!containsVertex(vertex)) + return false; + + // iterate over copy of incident edge collection + for (E edge : new ArrayList(vertices.get(vertex).values())) + removeEdge(edge); + + vertices.remove(vertex); + return true; + } + + public boolean removeEdge(E edge) + { + if (!containsEdge(edge)) + return false; + + Pair endpoints = getEndpoints(edge); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + // remove incident vertices from each others' adjacency maps + vertices.get(v1).remove(v2); + vertices.get(v2).remove(v1); + + edges.remove(edge); + return true; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraph.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraph.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,249 @@ +/* + * Created on Mar 6, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Oct 18, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * An implementation of UndirectedGraph that is suitable for + * sparse graphs and permits parallel edges. + */ +@SuppressWarnings("serial") +public class UndirectedSparseMultigraph + extends AbstractTypedGraph + implements UndirectedGraph, MultiGraph +{ + /** + * @param the vertex type for the graph Supplier + * @param the edge type for the graph Supplier + * @return a {@code Supplier} that creates an instance of this graph type. + */ + public static Supplier> getFactory() { + return new Supplier> () { + + public UndirectedGraph get() { + return new UndirectedSparseMultigraph(); + } + }; + } + + protected Map> vertices; // Map of vertices to adjacency sets + protected Map> edges; // Map of edges to incident vertex sets + + /** + * Creates a new instance. + */ + public UndirectedSparseMultigraph() { + super(EdgeType.UNDIRECTED); + vertices = new HashMap>(); + edges = new HashMap>(); + } + + public Collection getEdges() { + return Collections.unmodifiableCollection(edges.keySet()); + } + + public Collection getVertices() { + return Collections.unmodifiableCollection(vertices.keySet()); + } + + public boolean containsVertex(V vertex) { + return vertices.keySet().contains(vertex); + } + + public boolean containsEdge(E edge) { + return edges.keySet().contains(edge); + } + + protected Collection getIncident_internal(V vertex) + { + return vertices.get(vertex); + } + + public boolean addVertex(V vertex) { + if(vertex == null) { + throw new IllegalArgumentException("vertex may not be null"); + } + if (!containsVertex(vertex)) + { + vertices.put(vertex, new HashSet()); + return true; + } else { + return false; + } + } + + public boolean removeVertex(V vertex) { + if (!containsVertex(vertex)) + return false; + + for (E edge : new ArrayList(getIncident_internal(vertex))) + removeEdge(edge); + + vertices.remove(vertex); + return true; + } + + @Override + public boolean addEdge(E edge, V v1, V v2, EdgeType edgeType) { + return addEdge(edge, new Pair(v1, v2), edgeType); + } + + @Override + public boolean addEdge(E edge, Pair endpoints, EdgeType edge_type) + { + validateEdgeType(edge_type); + + Pair new_endpoints = getValidatedEndpoints(edge, endpoints); + if (new_endpoints == null) + return false; + + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + edges.put(edge, new_endpoints); + + if (!containsVertex(v1)) + this.addVertex(v1); + + if (!containsVertex(v2)) + this.addVertex(v2); + + vertices.get(v1).add(edge); + vertices.get(v2).add(edge); + + return true; + } + + public boolean removeEdge(E edge) { + if (!containsEdge(edge)) + return false; + + Pair endpoints = getEndpoints(edge); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + // remove edge from incident vertices' adjacency sets + vertices.get(v1).remove(edge); + vertices.get(v2).remove(edge); + + edges.remove(edge); + return true; + } + + public Collection getInEdges(V vertex) { + return this.getIncidentEdges(vertex); + } + + public Collection getOutEdges(V vertex) { + return this.getIncidentEdges(vertex); + } + + public Collection getPredecessors(V vertex) { + return this.getNeighbors(vertex); + } + + public Collection getSuccessors(V vertex) { + return this.getNeighbors(vertex); + } + + public Collection getNeighbors(V vertex) { + if (!containsVertex(vertex)) + return null; + + Set neighbors = new HashSet(); + for (E edge : getIncident_internal(vertex)) + { + Pair endpoints = this.getEndpoints(edge); + V e_a = endpoints.getFirst(); + V e_b = endpoints.getSecond(); + if (vertex.equals(e_a)) + neighbors.add(e_b); + else + neighbors.add(e_a); + } + + return Collections.unmodifiableCollection(neighbors); + } + + public Collection getIncidentEdges(V vertex) { + if (!containsVertex(vertex)) + return null; + + return Collections.unmodifiableCollection(getIncident_internal(vertex)); + } + + @Override + public E findEdge(V v1, V v2) { + if (!containsVertex(v1) || !containsVertex(v2)) + return null; + for (E edge : getIncident_internal(v1)) { + Pair endpoints = this.getEndpoints(edge); + V e_a = endpoints.getFirst(); + V e_b = endpoints.getSecond(); + if ((v1.equals(e_a) && v2.equals(e_b)) || (v1.equals(e_b) && v2.equals(e_a))) + return edge; + } + return null; + } + + public Pair getEndpoints(E edge) { + return edges.get(edge); + } + + public V getDest(E directed_edge) { + return null; + } + + public V getSource(E directed_edge) { + return null; + } + + public boolean isDest(V vertex, E edge) { + return false; + } + + public boolean isSource(V vertex, E edge) { + return false; + } + + public int getEdgeCount() { + return edges.size(); + } + + public int getVertexCount() { + return vertices.size(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/util/TestGraphs.java libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/util/TestGraphs.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/util/TestGraphs.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/main/java/edu/uci/ics/jung/graph/util/TestGraphs.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Jul 2, 2003 + * + */ +package edu.uci.ics.jung.graph.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +/** + * Provides generators for several different test graphs. + */ +public class TestGraphs { + + /** + * A series of pairs that may be useful for generating graphs. The + * miniature graph consists of 8 edges, 10 nodes, and is formed of two + * connected components, one of 8 nodes, the other of 2. + * + */ + public static String[][] pairs = { { "a", "b", "3" }, { + "a", "c", "4" }, { + "a", "d", "5" }, { + "d", "c", "6" }, { + "d", "e", "7" }, { + "e", "f", "8" }, { + "f", "g", "9" }, { + "h", "i", "1" } + }; + + /** + * Creates a small sample graph that can be used for testing purposes. The + * graph is as described in the section on {@link #pairs pairs}. If isDirected, + * the graph is a {@link DirectedSparseMultigraph DirectedSparseMultigraph}, + * otherwise, it is an {@link UndirectedSparseMultigraph UndirectedSparseMultigraph}. + * + * @param directed true iff the graph created is to have directed edges + * @return a graph consisting of eight edges and ten nodes. + */ + public static Graph createTestGraph(boolean directed) { + Graph graph = null; + if(directed) { + graph = new DirectedSparseMultigraph(); + } else { + graph = new UndirectedSparseMultigraph(); + } + + for (int i = 0; i < pairs.length; i++) { + String[] pair = pairs[i]; + graph.addEdge(Integer.parseInt(pair[2]), pair[0], pair[1]); + } + return graph; + } + + /** + * @param chain_length the length of the chain of vertices to add to the returned graph + * @param isolate_count the number of isolated vertices to add to the returned graph + * @return a graph consisting of a chain of {@code chain_length} vertices + * and {@code isolate_count} isolated vertices. + */ + public static Graph createChainPlusIsolates(int chain_length, int isolate_count) + { + Graph g = new UndirectedSparseMultigraph(); + if (chain_length > 0) + { + String[] v = new String[chain_length]; + v[0] = "v"+0; + g.addVertex(v[0]); + for (int i = 1; i < chain_length; i++) + { + v[i] = "v"+i; + g.addVertex(v[i]); + g.addEdge(new Double(Math.random()), v[i], v[i-1]); + } + } + for (int i = 0; i < isolate_count; i++) { + String v = "v"+(chain_length+i); + g.addVertex(v); + } + return g; + } + + /** + * Creates a sample directed acyclic graph by generating several "layers", + * and connecting nodes (randomly) to nodes in earlier (but never later) + * layers. The number of vertices in each layer is a random value in the range + * [1, maxNodesPerLayer]. + * + * @param layers the number of layers of vertices to create in the graph + * @param maxNodesPerLayer the maximum number of vertices to put in any layer + * @param linkprob the probability that this method will add an edge from a vertex in layer + * k to a vertex in layer k+1 + * @return the created graph + */ + public static Graph createDirectedAcyclicGraph( + int layers, + int maxNodesPerLayer, + double linkprob) { + + DirectedGraph dag = new DirectedSparseMultigraph(); + Set previousLayers = new HashSet(); + Set inThisLayer = new HashSet(); + for (int i = 0; i < layers; i++) { + + int nodesThisLayer = (int) (Math.random() * maxNodesPerLayer) + 1; + for (int j = 0; j < nodesThisLayer; j++) { + String v = i+":"+j; + dag.addVertex(v); + inThisLayer.add(v); + // for each previous node... + for(String v2 : previousLayers) { + if (Math.random() < linkprob) { + Double de = new Double(Math.random()); + dag.addEdge(de, v, v2); + } + } + } + + previousLayers.addAll(inThisLayer); + inThisLayer.clear(); + } + return dag; + } + + private static void createEdge( + Graph g, + String v1Label, + String v2Label, + int weight) { + g.addEdge(new Double(Math.random()), v1Label, v2Label); + } + + /** + * Returns a bigger, undirected test graph with a just one component. This + * graph consists of a clique of ten edges, a partial clique (randomly + * generated, with edges of 0.6 probability), and one series of edges + * running from the first node to the last. + * + * @return the testgraph + */ + public static Graph getOneComponentGraph() { + + UndirectedGraph g = new UndirectedSparseMultigraph(); + // let's throw in a clique, too + for (int i = 1; i <= 10; i++) { + for (int j = i + 1; j <= 10; j++) { + String i1 = "" + i; + String i2 = "" + j; + g.addEdge(Math.pow(i+2,j), i1, i2); + } + } + + // and, last, a partial clique + for (int i = 11; i <= 20; i++) { + for (int j = i + 1; j <= 20; j++) { + if (Math.random() > 0.6) + continue; + String i1 = "" + i; + String i2 = "" + j; + g.addEdge(Math.pow(i+2,j), i1, i2); + } + } + + List index = new ArrayList(); + index.addAll(g.getVertices()); + // and one edge to connect them all + for (int i = 0; i < index.size() - 1; i++) + g.addEdge(new Integer(i), index.get(i), index.get(i+1)); + + return g; + } + + /** + * Returns a bigger test graph with a clique, several components, and other + * parts. + * + * @return a demonstration graph of type UndirectedSparseMultigraph + * with 28 vertices. + */ + public static Graph getDemoGraph() { + UndirectedGraph g = + new UndirectedSparseMultigraph(); + + for (int i = 0; i < pairs.length; i++) { + String[] pair = pairs[i]; + createEdge(g, pair[0], pair[1], Integer.parseInt(pair[2])); + } + + // let's throw in a clique, too + for (int i = 1; i <= 10; i++) { + for (int j = i + 1; j <= 10; j++) { + String i1 = "c" + i; + String i2 = "c" + j; + g.addEdge(Math.pow(i+2,j), i1, i2); + } + } + + // and, last, a partial clique + for (int i = 11; i <= 20; i++) { + for (int j = i + 1; j <= 20; j++) { + if (Math.random() > 0.6) + continue; + String i1 = "p" + i; + String i2 = "p" + j; + g.addEdge(Math.pow(i+2,j), i1, i2); + } + } + return g; + } + + /** + * @return a small graph with directed and undirected edges, and parallel edges. + */ + public static Graph getSmallGraph() { + Graph graph = + new SparseMultigraph(); + String[] v = new String[3]; + for (int i = 0; i < 3; i++) { + v[i] = String.valueOf(i); + graph.addVertex(v[i]); + } + graph.addEdge(new Double(0), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(.1), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(.2), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(.3), v[1], v[0], EdgeType.DIRECTED); + graph.addEdge(new Double(.4), v[1], v[0], EdgeType.DIRECTED); + graph.addEdge(new Double(.5), v[1], v[2]); + graph.addEdge(new Double(.6), v[1], v[2]); + + return graph; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/site/site.xml libjung-free-java-2.1.1/jung-graph-impl/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/DirectedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/DirectedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/DirectedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/DirectedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ +package edu.uci.ics.jung.graph; + +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; + +public class DirectedSparseMultigraphTest + extends AbstractDirectedSparseMultigraphTest { + + + @Override + protected void setUp() throws Exception { + super.setUp(); + graph = new DirectedSparseMultigraph(); + graph.addEdge(e01, v0, v1); + graph.addEdge(e10, v1, v0); + graph.addEdge(e12, v1, v2); + graph.addEdge(e21, v2, v1); + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/HypergraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/HypergraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/HypergraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/HypergraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Created on Apr 21, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.graph; + +import junit.framework.Test; +import junit.framework.TestSuite; + +import com.google.common.base.Supplier; + + +public class HypergraphTest extends AbstractHypergraphTest +{ + + public HypergraphTest(Supplier> factory) + { + super(factory); + } + + @Override + public void setUp() + { + h = factory.get(); +// System.out.println(h.getClass().getSimpleName()); + } + + public static Test suite() + { + TestSuite ts = new TestSuite("HypergraphTest"); + + ts.addTest(new HypergraphTest(SetHypergraph.getFactory())); + ts.addTest(new HypergraphTest(DirectedOrderedSparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(DirectedSparseGraph.getFactory())); + ts.addTest(new HypergraphTest(DirectedSparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(OrderedSparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(SortedSparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(SparseGraph.getFactory())); + ts.addTest(new HypergraphTest(SparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(UndirectedOrderedSparseMultigraph.getFactory())); + ts.addTest(new HypergraphTest(UndirectedSparseGraph.getFactory())); + ts.addTest(new HypergraphTest(UndirectedSparseMultigraph.getFactory())); +// ts.addTest(new HypergraphTest(.getFactory())); + + return ts; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/OrderedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/OrderedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/OrderedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/OrderedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,49 @@ +package edu.uci.ics.jung.graph; + +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.graph.OrderedSparseMultigraph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; + +public class OrderedSparseMultigraphTest extends AbstractOrderedSparseMultigraphTest { + + + @Override + protected void setUp() throws Exception { + super.setUp(); + Set seeds = new HashSet(); + seeds.add(1); + seeds.add(5); + graph = new OrderedSparseMultigraph(); + graph.addEdge(4, 2, 1); + graph.addEdge(5, 3, 1); + graph.addEdge(6, 0, 4, EdgeType.DIRECTED); + graph.addEdge(7, 0, 5, EdgeType.DIRECTED); + graph.addEdge(1, 0, 1); + graph.addEdge(2, 1, 2); + graph.addEdge(3, 0, 2); + graph.addEdge(8, 5, 1, EdgeType.DIRECTED); + graph.addEdge(9, 6, 1, EdgeType.DIRECTED); + graph.addEdge(10, 4, 3, EdgeType.DIRECTED); + graph.addEdge(16, 8, 3); + graph.addEdge(17, 5, 7); + graph.addEdge(11, 2, 7); + graph.addEdge(12, 1, 5); + graph.addEdge(13, 2, 6); + graph.addEdge(14, 6, 4); + graph.addEdge(15, 7, 8); + + smallGraph = new SparseMultigraph(); + smallGraph.addVertex(v0); + smallGraph.addVertex(v1); + smallGraph.addVertex(v2); + smallGraph.addEdge(e01, v0, v1); + smallGraph.addEdge(e10, v1, v0); + smallGraph.addEdge(e12, v1, v2); + smallGraph.addEdge(e21, v2, v1, EdgeType.DIRECTED); + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SortedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SortedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SortedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SortedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,57 @@ +package edu.uci.ics.jung.graph; + +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.graph.util.EdgeType; + +public class SortedSparseMultigraphTest + extends AbstractSortedSparseMultigraphTest { + + + @Override + protected void setUp() throws Exception { + super.setUp(); + Set seeds = new HashSet(); + seeds.add(1); + seeds.add(5); + graph = new SortedSparseMultigraph(); + graph.addEdge(4., 2, 1); + graph.addEdge(5., 3, 1); + graph.addEdge(6., 0, 4, EdgeType.DIRECTED); + graph.addEdge(7., 0, 5, EdgeType.DIRECTED); + graph.addEdge(1., 0, 1); + graph.addEdge(2., 1, 2); + graph.addEdge(3., 0, 2); + graph.addEdge(8., 5, 1, EdgeType.DIRECTED); + graph.addEdge(9., 6, 1, EdgeType.DIRECTED); + graph.addEdge(10., 4, 3, EdgeType.DIRECTED); + graph.addEdge(16., 8, 3); + graph.addEdge(17., 5, 7); + graph.addEdge(11., 2, 7); + graph.addEdge(12., 1, 5); + graph.addEdge(13., 2, 6); + graph.addEdge(14., 6, 4); + graph.addEdge(15., 7, 8); + + smallGraph = new SparseMultigraph(); + smallGraph.addVertex(v0); + smallGraph.addVertex(v1); + smallGraph.addVertex(v2); + smallGraph.addEdge(e01, v0, v1); + smallGraph.addEdge(e10, v1, v0); + smallGraph.addEdge(e12, v1, v2); + smallGraph.addEdge(e21, v2, v1, EdgeType.DIRECTED); + + Graph fooBar = new SortedSparseMultigraph(); + try { + fooBar.addVertex(new Foo()); + fooBar.addVertex(new Foo()); + fooBar.addEdge(new Bar(), new Foo(), new Foo()); + fail("should have thrown an exception as Foo Bar are not Comparable"); + } catch(Exception ex) { + // all is well + } + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseGraphAddRemoveAddEdgeTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseGraphAddRemoveAddEdgeTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseGraphAddRemoveAddEdgeTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseGraphAddRemoveAddEdgeTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,25 @@ +package edu.uci.ics.jung.graph; + +import junit.framework.TestCase; + + +public class SparseGraphAddRemoveAddEdgeTest extends TestCase { + + SparseGraph g; + + + @Override + protected void setUp() throws Exception { + super.setUp(); + g = new SparseGraph(); + } + + public void testAddRemoveAddEdge() { + g.addVertex("A"); g.addVertex("B"); + g.addEdge(1, "A", "B"); + g.removeEdge(1); // Remove the edge between A and B + g.addEdge(2, "A", "B"); // Then add a different edge -> Exception thrown + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseMultigraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,49 @@ +package edu.uci.ics.jung.graph; + +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; + +public class SparseMultigraphTest + extends AbstractSparseMultigraphTest { + + + @Override + protected void setUp() throws Exception { + super.setUp(); + Set seeds = new HashSet(); + seeds.add(1); + seeds.add(5); + graph = new SparseMultigraph(); + graph.addEdge(1, 0, 1); + graph.addEdge(2, 1, 2); + graph.addEdge(3, 0, 2); + graph.addEdge(4, 2, 1); + graph.addEdge(5, 3, 1); + graph.addEdge(6, 0, 4, EdgeType.DIRECTED); + graph.addEdge(7, 0, 5, EdgeType.DIRECTED); + graph.addEdge(8, 5, 1, EdgeType.DIRECTED); + graph.addEdge(9, 6, 1, EdgeType.DIRECTED); + graph.addEdge(10, 4, 3, EdgeType.DIRECTED); + graph.addEdge(11, 2, 7); + graph.addEdge(12, 1, 5); + graph.addEdge(13, 2, 6); + graph.addEdge(14, 6, 4); + graph.addEdge(15, 7, 8); + graph.addEdge(16, 8, 3); + graph.addEdge(17, 5, 7); + + smallGraph = new SparseMultigraph(); + smallGraph.addVertex(v0); + smallGraph.addVertex(v1); + smallGraph.addVertex(v2); + smallGraph.addEdge(e01, v0, v1); + smallGraph.addEdge(e10, v1, v0); + smallGraph.addEdge(e12, v1, v2); + smallGraph.addEdge(e21, v2, v1, EdgeType.DIRECTED); + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseTreeTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseTreeTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseTreeTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/SparseTreeTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,21 @@ +package edu.uci.ics.jung.graph; + +import com.google.common.base.Supplier; + +public class SparseTreeTest extends AbstractSparseTreeTest { + + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + graphFactory = DirectedSparseMultigraph.getFactory(); + edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + tree = new DelegateTree(graphFactory); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/TreeUtilsTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/TreeUtilsTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/TreeUtilsTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/TreeUtilsTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,23 @@ +package edu.uci.ics.jung.graph; + +import edu.uci.ics.jung.graph.DelegateTree; + +public class TreeUtilsTest extends AbstractTreeUtilsTest { + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + tree = new DelegateTree(); + tree.addVertex("A"); + tree.addEdge(1, "A", "B0"); + tree.addEdge(2, "A", "B1"); + tree.addEdge(3, "B0", "C0"); + tree.addEdge(4, "C0", "D0"); + tree.addEdge(5, "C0", "D1"); + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraphTest.java libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraphTest.java --- libjung-free-java-2.0.1+dfsg/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraphTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-graph-impl/src/test/java/edu/uci/ics/jung/graph/UndirectedSparseMultigraphTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,18 @@ +package edu.uci.ics.jung.graph; + +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; + +public class UndirectedSparseMultigraphTest + extends AbstractUndirectedSparseMultigraphTest { + + @Override + protected void setUp() throws Exception { + super.setUp(); + graph = new UndirectedSparseMultigraph(); + graph.addEdge(e01, v0, v1); + graph.addEdge(e10, v1, v0); + graph.addEdge(e12, v1, v2); + graph.addEdge(e21, v2, v1); + + } +} Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-graph-impl-2.0.1-sources.jar and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-graph-impl-2.0.1-sources.jar differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/pom.xml libjung-free-java-2.1.1/jung-io/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-io/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-io + JUNG - I/O Support + IO support classes for JUNG + + + + net.sf.jung + jung-api + ${project.version} + + + net.sf.jung + jung-algorithms + ${project.version} + + + net.sf.jung + jung-graph-impl + ${project.version} + test + + + junit + junit + test + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphFile.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphFile.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphFile.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphFile.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Jan 6, 2002 + * + */ +package edu.uci.ics.jung.io; + +import edu.uci.ics.jung.graph.Graph; + + +/** + * General interface for loading and saving a graph from/to disk. + * @author Scott + * @author Tom Nelson - converted to jung2 + * + */ +public interface GraphFile { + + /** + * Loads a graph from a file per the appropriate format + * @param filename the location and name of the file + * @return the graph + */ + Graph load(String filename); + + /** + * Save a graph to disk per the appropriate format + * @param graph the location and name of the file + * @param filename the graph + */ + void save(Graph graph, String filename); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphIOException.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphIOException.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphIOException.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphIOException.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io; + +/** + * Exception thrown when IO errors occur when reading/writing graphs. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class GraphIOException extends Exception { + + private static final long serialVersionUID = 3773882099782535606L; + + /** + * Creates a new instance with no specified message or cause. + */ + public GraphIOException() { + super(); + } + + /** + * Creates a new instance with the specified message and cause. + * @param message a description of the exception-triggering event + * @param cause the exception which triggered this one + */ + public GraphIOException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Creates a new instance with the specified message and no + * specified cause. + * @param message a description of the exception-triggering event + */ + public GraphIOException(String message) { + super(message); + } + + /** + * Creats a new instance with the specified cause and no specified message. + * @param cause the exception which triggered this one + */ + public GraphIOException(Throwable cause) { + super(cause); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/AbstractMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/AbstractMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/AbstractMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/AbstractMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.HashMap; +import java.util.Map; + +/** + * Abstract base class for metadata - implements the property functionality + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public abstract class AbstractMetadata implements Metadata { + + final private Map properties = new HashMap(); + + public Map getProperties() { + return properties; + } + + public String getProperty(String key) { + return properties.get(key); + } + + public String setProperty(String key, String value) { + return properties.put(key, value); + } + + public void addData(DataMetadata data) { + properties.put(data.getKey(), data.getValue()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/DataMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/DataMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/DataMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/DataMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +/** + * Metadata structure for the 'data' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class DataMetadata { + + private String key; + private String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EdgeMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EdgeMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EdgeMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EdgeMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +/** + * Metadata structure for the 'edge' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class EdgeMetadata extends AbstractMetadata { + + private String id; + private Boolean directed; + private String source; + private String target; + private String sourcePort; + private String targetPort; + private String description; + private Object edge; + + public String getId() { + return id; + } + + + public void setId(String id) { + this.id = id; + } + + + public Boolean isDirected() { + return directed; + } + + + public void setDirected(Boolean directed) { + this.directed = directed; + } + + + public String getSource() { + return source; + } + + + public void setSource(String source) { + this.source = source; + } + + + public String getTarget() { + return target; + } + + + public void setTarget(String target) { + this.target = target; + } + + + public String getSourcePort() { + return sourcePort; + } + + + public void setSourcePort(String sourcePort) { + this.sourcePort = sourcePort; + } + + + public String getTargetPort() { + return targetPort; + } + + + public void setTargetPort(String targetPort) { + this.targetPort = targetPort; + } + + + public String getDescription() { + return description; + } + + + public void setDescription(String description) { + this.description = description; + } + + public Object getEdge() { + return edge; + } + + + public void setEdge(Object edge) { + this.edge = edge; + } + + + public MetadataType getMetadataType() { + return MetadataType.EDGE; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EndpointMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EndpointMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EndpointMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/EndpointMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +/** + * Metadata structure for the 'endpoint' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class EndpointMetadata extends AbstractMetadata { + + public enum EndpointType { + IN, + OUT, + UNDIR + } + + private String id; + private String port; + private String node; + private String description; + private EndpointType endpointType = EndpointType.UNDIR; + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + public String getPort() { + return port; + } + public void setPort(String port) { + this.port = port; + } + public String getNode() { + return node; + } + public void setNode(String node) { + this.node = node; + } + public EndpointType getEndpointType() { + return endpointType; + } + public void setEndpointType(EndpointType endpointType) { + this.endpointType = endpointType; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public MetadataType getMetadataType() { + return MetadataType.ENDPOINT; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/ExceptionConverter.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/ExceptionConverter.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/ExceptionConverter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/ExceptionConverter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import edu.uci.ics.jung.io.GraphIOException; + +import javax.xml.stream.XMLStreamException; + +/** + * Converts an exception to the a GraphIOException. Runtime exceptions + * are checked for the cause. If the cause is an XMLStreamException, it is + * converted to a GraphIOException. Otherwise, the RuntimeException is + * rethrown. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class ExceptionConverter { + + /** + * Converts an exception to the a GraphIOException. Runtime exceptions + * are checked for the cause. If the cause is an XMLStreamException, it is + * converted to a GraphReaderException. Otherwise, the RuntimeException is + * rethrown. + * + * @param e the exception to be converted + * @throws GraphIOException the converted exception + */ + static public void convert(Exception e) throws GraphIOException { + + if (e instanceof GraphIOException) { + throw (GraphIOException) e; + } + + if (e instanceof RuntimeException) { + + // If the cause was an XMLStreamException, throw a GraphReaderException + if (e.getCause() instanceof XMLStreamException) { + throw new GraphIOException(e.getCause()); + } + + throw (RuntimeException) e; + } + + throw new GraphIOException(e); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.HashMap; +import java.util.Map; + +/** + * Metadata structure for the 'graph' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class GraphMetadata extends AbstractMetadata { + + public enum EdgeDefault { + DIRECTED, UNDIRECTED + } + + private String id; + private EdgeDefault edgeDefault; + private String description; + private Object graph; + final private Map nodes = new HashMap(); + final private Map edges = new HashMap(); + final private Map hyperEdges = new HashMap(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public EdgeDefault getEdgeDefault() { + return edgeDefault; + } + + public void setEdgeDefault(EdgeDefault edgeDefault) { + this.edgeDefault = edgeDefault; + } + + public String getDescription() { + return description; + } + + public void setDescription(String desc) { + this.description = desc; + } + + public void addNodeMetadata(Object vertex, NodeMetadata metadata) { + nodes.put(vertex, metadata); + } + + public NodeMetadata getNodeMetadata(Object vertex) { + return nodes.get(vertex); + } + + public Map getNodeMap() { + return nodes; + } + + public void addEdgeMetadata(Object edge, EdgeMetadata metadata) { + edges.put(edge, metadata); + } + + public EdgeMetadata getEdgeMetadata(Object edge) { + return edges.get(edge); + } + + public Map getEdgeMap() { + return edges; + } + + public void addHyperEdgeMetadata(Object edge, HyperEdgeMetadata metadata) { + hyperEdges.put(edge, metadata); + } + + public HyperEdgeMetadata getHyperEdgeMetadata(Object edge) { + return hyperEdges.get(edge); + } + + public Map getHyperEdgeMap() { + return hyperEdges; + } + + public Object getGraph() { + return graph; + } + + public void setGraph(Object graph) { + this.graph = graph; + } + + public MetadataType getMetadataType() { + return MetadataType.GRAPH; + } + + /** + * Gets the property for the given vertex object. + * + * @param vertex + * the subject vertex + * @param key + * the property key + * @return the property value + * @throws IllegalArgumentException + * thrown if there is no metadata associated with the provided + * vertex object. + */ + public String getVertexProperty(Object vertex, String key) + throws IllegalArgumentException { + NodeMetadata metadata = getNodeMetadata(vertex); + if (metadata == null) { + throw new IllegalArgumentException( + "Metadata does not exist for provided vertex"); + } + + return metadata.getProperty(key); + } + + /** + * Gets the property for the given edge object. + * + * @param edge + * the subject edge. + * @param key + * the property key + * @return the property value + * @throws IllegalArgumentException + * thrown if there is no metadata associated with the provided + * edge object. + */ + public String getEdgeProperty(Object edge, String key) + throws IllegalArgumentException { + + // First, try standard edges. + EdgeMetadata em = getEdgeMetadata(edge); + if (em != null) { + return em.getProperty(key); + } + + // Next, try hyperedges. + HyperEdgeMetadata hem = getHyperEdgeMetadata(edge); + if (hem != null) { + return hem.getProperty(key); + } + + // Couldn't find the edge. + throw new IllegalArgumentException( + "Metadata does not exist for provided edge"); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLConstants.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLConstants.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLConstants.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLConstants.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +/** + * Provides some constants for element/attribute names in GraphML + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class GraphMLConstants { + + public static final String GRAPHML_NAME = "graphml"; + public static final String GRAPH_NAME = "graph"; + public static final String NODE_NAME = "node"; + public static final String EDGE_NAME = "edge"; + public static final String ENDPOINT_NAME = "endpoint"; + public static final String HYPEREDGE_NAME = "hyperedge"; + public static final String PORT_NAME = "port"; + public static final String KEY_NAME = "key"; + public static final String DATA_NAME = "data"; + public static final String ALL_NAME = "all"; + public static final String ID_NAME = "id"; + public static final String FOR_NAME = "for"; + public static final String DESC_NAME = "desc"; + public static final String DEFAULT_NAME = "default"; + public static final String ATTRNAME_NAME = "attr.name"; + public static final String ATTRTYPE_NAME = "attr.type"; + public static final String NAME_NAME = "name"; + public static final String EDGEDEFAULT_NAME = "edgedefault"; + public static final String TYPE_NAME = "type"; + public static final String IN_NAME = "in"; + public static final String OUT_NAME = "out"; + public static final String UNDIR_NAME = "undir"; + public static final String DIRECTED_NAME = "directed"; + public static final String UNDIRECTED_NAME = "undirected"; + public static final String SOURCE_NAME = "source"; + public static final String TARGET_NAME = "target"; + public static final String SOURCEPORT_NAME = "sourceport"; + public static final String TARGETPORT_NAME = "targetport"; +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLDocument.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLDocument.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLDocument.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLDocument.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Maintains all the metadata read in from a single GraphML XML document. + */ +public class GraphMLDocument { + + final private KeyMap keyMap = new KeyMap(); + final private List graphMetadata = new ArrayList(); + + public KeyMap getKeyMap() { + return keyMap; + } + + public List getGraphMetadata() { + return graphMetadata; + } + + public void clear() { + graphMetadata.clear(); + keyMap.clear(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLReader2.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLReader2.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLReader2.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/GraphMLReader2.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.io.IOException; +import java.io.Reader; +import java.io.InputStream; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.GraphReader; +import edu.uci.ics.jung.io.graphml.parser.ElementParserRegistry; +import edu.uci.ics.jung.io.graphml.parser.GraphMLEventFilter; + +/** + * Reads in data from a GraphML-formatted file and generates graphs based on + * that data. Does not currently support nested graphs. + * + *

    Note that the user is responsible for supplying a graph + * Transformer that will create graphs capable of supporting the + * edge types in the supplied GraphML file. If the graph generated by the + * Factory is not compatible (for example: if the graph does not + * accept directed edges, and the GraphML file contains a directed edge) then + * the results are graph-implementation-dependent. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @param + * The graph type to be read from the GraphML file + * @param the vertex type + * The vertex type used by the graph + * @param the edge type + * The edge type used by the graph + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class GraphMLReader2, V, E> implements + GraphReader { + + protected XMLEventReader xmlEventReader; + protected Reader fileReader; + protected Function graphTransformer; + protected Function vertexTransformer; + protected Function edgeTransformer; + protected Function hyperEdgeTransformer; + protected boolean initialized; + final protected GraphMLDocument document = new GraphMLDocument(); + final protected ElementParserRegistry parserRegistry; + private InputStream inputStream ; + + /** + * Constructs a GraphML reader around the given reader. This constructor + * requires the user to supply transformation functions to convert from the + * GraphML metadata to Graph, Vertex, Edge instances. These Function + * functions can be used as purely factories (i.e. the metadata is + * disregarded) or can use the metadata to set particular fields in the + * objects. + * + * @param fileReader the reader for the input GraphML document. + * @param graphTransformer Transformation function to convert from GraphML GraphMetadata + * to graph objects. This must be non-null. + * @param vertexTransformer Transformation function to convert from GraphML NodeMetadata + * to vertex objects. This must be non-null. + * @param edgeTransformer Transformation function to convert from GraphML EdgeMetadata + * to edge objects. This must be non-null. + * @param hyperEdgeTransformer Transformation function to convert from GraphML + * HyperEdgeMetadata to edge objects. This must be non-null. + * @throws IllegalArgumentException thrown if any of the arguments are null. + */ + public GraphMLReader2(Reader fileReader, + Function graphTransformer, + Function vertexTransformer, + Function edgeTransformer, + Function hyperEdgeTransformer) { + + if (fileReader == null) { + throw new IllegalArgumentException( + "Argument fileReader must be non-null"); + } + + if (graphTransformer == null) { + throw new IllegalArgumentException( + "Argument graphTransformer must be non-null"); + } + + if (vertexTransformer == null) { + throw new IllegalArgumentException( + "Argument vertexTransformer must be non-null"); + } + + if (edgeTransformer == null) { + throw new IllegalArgumentException( + "Argument edgeTransformer must be non-null"); + } + + if (hyperEdgeTransformer == null) { + throw new IllegalArgumentException( + "Argument hyperEdgeTransformer must be non-null"); + } + + this.fileReader = fileReader; + this.graphTransformer = graphTransformer; + this.vertexTransformer = vertexTransformer; + this.edgeTransformer = edgeTransformer; + this.hyperEdgeTransformer = hyperEdgeTransformer; + + // Create the parser registry. + this.parserRegistry = new ElementParserRegistry(document.getKeyMap(), + graphTransformer, vertexTransformer, edgeTransformer, hyperEdgeTransformer); + } + + /** + * Constructs a GraphML reader around the given reader. This constructor + * requires the user to supply transformation functions to convert from the + * GraphML metadata to Graph, Vertex, Edge instances. These Function + * functions can be used as purely factories (i.e. the metadata is + * disregarded) or can use the metadata to set particular fields in the + * objects. + * + * @param inputStream the inputstream for the input GraphML document. + * @param graphTransformer Transformation function to convert from GraphML GraphMetadata + * to graph objects. This must be non-null. + * @param vertexTransformer Transformation function to convert from GraphML NodeMetadata + * to vertex objects. This must be non-null. + * @param edgeTransformer Transformation function to convert from GraphML EdgeMetadata + * to edge objects. This must be non-null. + * @param hyperEdgeTransformer Transformation function to convert from GraphML + * HyperEdgeMetadata to edge objects. This must be non-null. + * @throws IllegalArgumentException thrown if any of the arguments are null. + */ + public GraphMLReader2(InputStream inputStream, + Function graphTransformer, + Function vertexTransformer, + Function edgeTransformer, + Function hyperEdgeTransformer) { + + if (inputStream == null) { + throw new IllegalArgumentException( + "Argument inputStream must be non-null"); + } + + if (graphTransformer == null) { + throw new IllegalArgumentException( + "Argument graphTransformer must be non-null"); + } + + if (vertexTransformer == null) { + throw new IllegalArgumentException( + "Argument vertexTransformer must be non-null"); + } + + if (edgeTransformer == null) { + throw new IllegalArgumentException( + "Argument edgeTransformer must be non-null"); + } + + if (hyperEdgeTransformer == null) { + throw new IllegalArgumentException( + "Argument hyperEdgeTransformer must be non-null"); + } + + this.inputStream = inputStream; + this.graphTransformer = graphTransformer; + this.vertexTransformer = vertexTransformer; + this.edgeTransformer = edgeTransformer; + this.hyperEdgeTransformer = hyperEdgeTransformer; + + // Create the parser registry. + this.parserRegistry = new ElementParserRegistry(document.getKeyMap(), + graphTransformer, vertexTransformer, edgeTransformer, hyperEdgeTransformer); + } + + /** + * Gets the current Function that is being used for graph objects. + * + * @return the current Function. + */ + public Function getGraphTransformer() { + return graphTransformer; + } + + /** + * Gets the current Function that is being used for vertex objects. + * + * @return the current Function. + */ + public Function getVertexTransformer() { + return vertexTransformer; + } + + /** + * Gets the current Function that is being used for edge objects. + * + * @return the current Function. + */ + public Function getEdgeTransformer() { + return edgeTransformer; + } + + /** + * Gets the current Function that is being used for hyperedge objects. + * + * @return the current Function. + */ + public Function getHyperEdgeTransformer() { + return hyperEdgeTransformer; + } + + /** + * Verifies the object state and initializes this reader. All Function + * properties must be set and be non-null or a GraphReaderException + * will be thrown. This method may be called more than once. + * Successive calls will have no effect. + * + * @throws edu.uci.ics.jung.io.GraphIOException thrown if an error occurred. + */ + public void init() throws GraphIOException { + + try { + + if (!initialized) { + + // Create the event reader. + XMLInputFactory Supplier = XMLInputFactory.newInstance(); + if(fileReader==null && inputStream != null) { + xmlEventReader = Supplier.createXMLEventReader(inputStream); + } else { + xmlEventReader = Supplier.createXMLEventReader(fileReader); + } + xmlEventReader = Supplier.createFilteredReader(xmlEventReader, + new GraphMLEventFilter()); + + initialized = true; + } + + } catch( Exception e ) { + ExceptionConverter.convert(e); + } + } + + /** + * Closes the GraphML reader and disposes of any resources. + * + * @throws edu.uci.ics.jung.io.GraphIOException thrown if an error occurs. + */ + public void close() throws GraphIOException { + try { + + // Clear the contents of the document. + document.clear(); + + if (xmlEventReader != null) { + xmlEventReader.close(); + } + + if (fileReader != null) { + fileReader.close(); + } + + if (inputStream != null) { + inputStream.close(); + } + + } catch (IOException e) { + throw new GraphIOException(e); + } catch (XMLStreamException e) { + throw new GraphIOException(e); + } finally { + fileReader = null; + inputStream = null; + xmlEventReader = null; + graphTransformer = null; + vertexTransformer = null; + edgeTransformer = null; + hyperEdgeTransformer = null; + } + } + + /** + * Returns the object that contains the metadata read in from the GraphML + * document + * + * @return the GraphML document + */ + public GraphMLDocument getGraphMLDocument() { + return document; + } + + /** + * Reads a single graph object from the GraphML document. Automatically + * calls init to initialize the state of the reader. + * + * @return the graph that was read if one was found, otherwise null. + */ + @SuppressWarnings("unchecked") + public G readGraph() throws GraphIOException { + + try { + + // Initialize if not already. + init(); + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + String name = element.getName().getLocalPart(); + + // The element should be one of: key, graph, graphml + if (GraphMLConstants.KEY_NAME.equals(name)) { + + // Parse the key object. + Key key = (Key) parserRegistry.getParser(name).parse( + xmlEventReader, element); + + // Add the key to the key map. + document.getKeyMap().addKey(key); + + } else if (GraphMLConstants.GRAPH_NAME.equals(name)) { + + // Parse the graph. + GraphMetadata graph = (GraphMetadata) parserRegistry + .getParser(name).parse(xmlEventReader, element); + + // Add it to the graph metadata list. + document.getGraphMetadata().add(graph); + + // Return the graph object. + return (G)graph.getGraph(); + + } else if (GraphMLConstants.GRAPHML_NAME.equals(name)) { + // Ignore the graphML object. + } else { + + // Encounted an unknown element - just skip by it. + parserRegistry.getUnknownElementParser().parse( + xmlEventReader, element); + } + + } else if (event.isEndDocument()) { + break; + } + } + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + // We didn't read anything from the document. + throw new GraphIOException("Unable to read Graph from document - the document could be empty"); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/HyperEdgeMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/HyperEdgeMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/HyperEdgeMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/HyperEdgeMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Metadata structure for the 'hyperedge' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class HyperEdgeMetadata extends AbstractMetadata { + + private String id; + private String description; + private Object edge; + final private List endpoints = new ArrayList(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public void addEndpoint( EndpointMetadata endpoint ) { + endpoints.add(endpoint); + } + + public List getEndpoints() { + return endpoints; + } + + public Object getEdge() { + return edge; + } + + public void setEdge(Object edge) { + this.edge = edge; + } + + public MetadataType getMetadataType() { + return MetadataType.HYPEREDGE; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Key.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Key.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Key.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Key.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.Map; + +/** + * GraphML key object that was parsed from the input stream. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class Key { + + /** + * Enumeration for the 'for' type of this key. The for property indicates + * which elements (e.g. graph, node, edge) this key applies to. + */ + public enum ForType { + ALL, GRAPH, NODE, EDGE, HYPEREDGE, PORT, ENDPOINT + } + + private String id; + private String description; + private String attributeName; + private String attributeType; + private String defaultValue; + private ForType forType = ForType.ALL; + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getAttributeName() { + return attributeName; + } + + public void setAttributeName(String attributeName) { + this.attributeName = attributeName; + } + + public String getAttributeType() { + return attributeType; + } + + public void setAttributeType(String attributeType) { + this.attributeType = attributeType; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public void setId(String id) { + this.id = id; + } + + public void setForType(ForType forType) { + this.forType = forType; + } + + public String getId() { + return this.id; + } + + public String defaultValue() { + return this.defaultValue; + } + + public ForType getForType() { + return this.forType; + } + + public void applyKey( Metadata metadata ) { + Map props = metadata.getProperties(); + if( defaultValue != null && !props.containsKey(id) ) { + props.put(id, defaultValue); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/KeyMap.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/KeyMap.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/KeyMap.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/KeyMap.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * A KeyMap is a storage mechanism for the keys read from the GraphML file. It + * stores the keys indexed by the type of GraphML metadata (node, edge, etc) + * that the key applies to. The applyKeys method will obtain the + * list of keys that apply to the given metadata type and apply the keys + * one-by-one to the metadata. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class KeyMap { + + final private Map> map = new HashMap>(); + + /** + * Adds the given key to the map. + * + * @param key the key to be added. + */ + public void addKey(Key key) { + + switch (key.getForType()) { + case EDGE: { + getKeyList(Metadata.MetadataType.EDGE).add(key); + break; + } + case ENDPOINT: { + getKeyList(Metadata.MetadataType.ENDPOINT).add(key); + break; + } + case GRAPH: { + getKeyList(Metadata.MetadataType.GRAPH).add(key); + break; + } + case HYPEREDGE: { + getKeyList(Metadata.MetadataType.HYPEREDGE).add(key); + break; + } + case NODE: { + getKeyList(Metadata.MetadataType.NODE).add(key); + break; + } + case PORT: { + getKeyList(Metadata.MetadataType.PORT).add(key); + break; + } + default: { + + // Default = ALL + getKeyList(Metadata.MetadataType.EDGE).add(key); + getKeyList(Metadata.MetadataType.ENDPOINT).add(key); + getKeyList(Metadata.MetadataType.GRAPH).add(key); + getKeyList(Metadata.MetadataType.HYPEREDGE).add(key); + getKeyList(Metadata.MetadataType.NODE).add(key); + getKeyList(Metadata.MetadataType.PORT).add(key); + } + } + } + + /** + * Applies all keys that are applicable to the given metadata. + * + * @param metadata the target metadata. + */ + public void applyKeys(Metadata metadata) { + + List keys = getKeyList(metadata.getMetadataType()); + for (Key key : keys) { + key.applyKey(metadata); + } + } + + /** + * Clears this map. + */ + public void clear() { + map.clear(); + } + + /** + * Retrieves the set of entries contained in this map. + * + * @return all of the entries in this map. + */ + public Set>> entrySet() { + return map.entrySet(); + } + + /** + * Gets the list for the given metadata type. If doesn't exist, the list is + * created. + * + * @param type the metadata type. + * @return the list for the metadata type. + */ + private List getKeyList(Metadata.MetadataType type) { + + List keys = map.get(type); + if (keys == null) { + keys = new ArrayList(); + map.put(type, keys); + } + + return keys; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Metadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Metadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Metadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/Metadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.Map; + +/** + * Interface for any GraphML metadata. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public interface Metadata { + + /** + * Metadata type enumeration + */ + enum MetadataType { + GRAPH, NODE, EDGE, HYPEREDGE, PORT, ENDPOINT + } + + /** + * Gets the metadata type of this object. + * + * @return the metadata type + */ + MetadataType getMetadataType(); + + /** + * Gets any properties that were associated with this metadata in the + * GraphML + * + * @return GraphML properties + */ + Map getProperties(); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/NodeMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/NodeMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/NodeMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/NodeMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Metadata structure for the 'node' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class NodeMetadata extends AbstractMetadata { + + private String id; + private String description; + private Object vertex; + final private List ports = new ArrayList(); + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String desc) { + this.description = desc; + } + + public void addPort(PortMetadata port) { + ports.add(port); + } + + public List getPorts() { + return ports; + } + + public Object getVertex() { + return vertex; + } + + public void setVertex(Object vertex) { + this.vertex = vertex; + } + + public MetadataType getMetadataType() { + return MetadataType.NODE; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/AbstractElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/AbstractElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/AbstractElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/AbstractElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.Metadata; + +/** + * Base class for element parsers - provides some minimal functionality. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public abstract class AbstractElementParser,V,E> implements ElementParser { + + final private ParserContext parserContext; + protected AbstractElementParser(ParserContext parserContext) { + this.parserContext = parserContext; + } + + public ParserContext getParserContext() { + return this.parserContext; + } + + public ElementParser getParser(String localName) { + return parserContext.getElementParserRegistry().getParser(localName); + } + + public void applyKeys(Metadata metadata) { + getParserContext().getKeyMap().applyKeys(metadata); + } + + public ElementParser getUnknownParser() { + return parserContext.getElementParserRegistry().getUnknownElementParser(); + } + + protected void verifyMatch(StartElement start, EndElement end) + throws GraphIOException { + + String startName = start.getName().getLocalPart(); + String endName = end.getName().getLocalPart(); + if (!startName.equals(endName)) { + throw new GraphIOException( + "Failed parsing document: Start/end tag mismatch! " + + "StartTag:" + startName + ", EndTag: " + + endName); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/DataElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/DataElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/DataElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/DataElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.DataMetadata; +import edu.uci.ics.jung.io.graphml.GraphMLConstants; +import edu.uci.ics.jung.io.graphml.ExceptionConverter; + +/** + * Parses the data element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class DataElementParser,V,E> extends AbstractElementParser { + + public DataElementParser(ParserContext parserContext) { + super(parserContext); + } + + public DataMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new port. + DataMetadata data = new DataMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = (Attribute) iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (data.getKey() == null && GraphMLConstants.KEY_NAME.equals(name)) { + data.setKey(value); + } + } + + // Make sure the key has been set. + if (data.getKey() == null) { + throw new GraphIOException( + "Element 'data' is missing attribute 'key'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + // Treat any child elements as unknown + getUnknownParser().parse(xmlEventReader, element); + } + if (event.isCharacters()) { + Characters characters = (Characters) event; + data.setValue(characters.getData()); + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + return data; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EdgeElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EdgeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EdgeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EdgeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.*; + +/** + * Parses an edge element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class EdgeElementParser,V,E> extends AbstractElementParser { + + public EdgeElementParser(ParserContext parserContext) { + super(parserContext); + } + + public EdgeMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new edge. + EdgeMetadata edge = new EdgeMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (edge.getId() == null && GraphMLConstants.ID_NAME.equals(name)) { + edge.setId(value); + } else if (edge.isDirected() == null && GraphMLConstants.DIRECTED_NAME.equals(name)) { + edge.setDirected(("true".equals(value))); + } else if (edge.getSource() == null && GraphMLConstants.SOURCE_NAME.equals(name)) { + edge.setSource(value); + } else if (edge.getTarget() == null && GraphMLConstants.TARGET_NAME.equals(name)) { + edge.setTarget(value); + } else if (edge.getSourcePort() == null && GraphMLConstants.SOURCEPORT_NAME.equals(name)) { + edge.setSourcePort(value); + } else if (edge.getTargetPort() == null && GraphMLConstants.TARGETPORT_NAME.equals(name)) { + edge.setTargetPort(value); + } else { + edge.setProperty(name, value); + } + } + + // Make sure the source and target have been been set. + if (edge.getSource() == null || edge.getTarget() == null) { + throw new GraphIOException( + "Element 'edge' is missing attribute 'source' or 'target'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + edge.setDescription(desc); + } else if(GraphMLConstants.DATA_NAME.equals(name)) { + DataMetadata data = (DataMetadata)getParser(name).parse(xmlEventReader, element); + edge.addData(data); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this object. + applyKeys(edge); + + return edge; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; + +import edu.uci.ics.jung.io.GraphIOException; + +/** + * Interface for all element parsers. All parsers will be registered with the registry. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see ElementParserRegistry + */ +public interface ElementParser { + Object parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException; +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParserRegistry.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParserRegistry.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParserRegistry.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ElementParserRegistry.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.graphml.EdgeMetadata; +import edu.uci.ics.jung.io.graphml.GraphMLConstants; +import edu.uci.ics.jung.io.graphml.GraphMetadata; +import edu.uci.ics.jung.io.graphml.HyperEdgeMetadata; +import edu.uci.ics.jung.io.graphml.KeyMap; +import edu.uci.ics.jung.io.graphml.NodeMetadata; + +/** + * Registry for all element parsers. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class ElementParserRegistry, V, E> { + + final private Map parserMap = new HashMap(); + + final private ElementParser unknownElementParser = new UnknownElementParser(); + + public ElementParserRegistry(KeyMap keyMap, + Function graphTransformer, + Function vertexTransformer, + Function edgeTransformer, + Function hyperEdgeTransformer) { + + // Create the parser context. + ParserContext context = new ParserContext(this, keyMap, graphTransformer, + vertexTransformer, edgeTransformer, hyperEdgeTransformer); + + parserMap.put(GraphMLConstants.DEFAULT_NAME, new StringElementParser(context)); + parserMap.put(GraphMLConstants.DESC_NAME, new StringElementParser(context)); + parserMap.put(GraphMLConstants.KEY_NAME, new KeyElementParser(context)); + parserMap.put(GraphMLConstants.DATA_NAME, new DataElementParser(context)); + parserMap.put(GraphMLConstants.PORT_NAME, new PortElementParser(context)); + parserMap.put(GraphMLConstants.NODE_NAME, new NodeElementParser(context)); + parserMap.put(GraphMLConstants.GRAPH_NAME, new GraphElementParser(context)); + parserMap.put(GraphMLConstants.ENDPOINT_NAME, new EndpointElementParser(context)); + parserMap.put(GraphMLConstants.EDGE_NAME, new EdgeElementParser(context)); + parserMap.put(GraphMLConstants.HYPEREDGE_NAME, new HyperEdgeElementParser(context)); + } + + public ElementParser getUnknownElementParser() { + return unknownElementParser; + } + + public ElementParser getParser(String localName) { + ElementParser parser = parserMap.get(localName); + if (parser == null) { + parser = unknownElementParser; + } + + return parser; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EndpointElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EndpointElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EndpointElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/EndpointElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.EndpointMetadata; +import edu.uci.ics.jung.io.graphml.GraphMLConstants; +import edu.uci.ics.jung.io.graphml.ExceptionConverter; +import edu.uci.ics.jung.io.graphml.EndpointMetadata.EndpointType; + +/** + * Parses endpoint elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class EndpointElementParser,V,E> extends AbstractElementParser { + + final static private Map endpointTypeMap = new HashMap(); + static { + endpointTypeMap.put(GraphMLConstants.IN_NAME, EndpointType.IN); + endpointTypeMap.put(GraphMLConstants.OUT_NAME, EndpointType.OUT); + endpointTypeMap.put(GraphMLConstants.UNDIR_NAME, EndpointType.UNDIR); + } + + public EndpointElementParser(ParserContext parserContext) { + super(parserContext); + } + + public EndpointMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new endpoint. + EndpointMetadata endpoint = new EndpointMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (endpoint.getId() == null && GraphMLConstants.ID_NAME.equals(name)) { + endpoint.setId(value); + } if (endpoint.getPort() == null && GraphMLConstants.PORT_NAME.equals(name)) { + endpoint.setPort(value); + } if (endpoint.getNode() == null && GraphMLConstants.NODE_NAME.equals(name)) { + endpoint.setNode(value); + } if (GraphMLConstants.TYPE_NAME.equals(name)) { + EndpointType t = endpointTypeMap.get(value); + if( t == null ) { + t = EndpointType.UNDIR; + } + endpoint.setEndpointType(t); + } else { + endpoint.setProperty(name, value); + } + } + + // Make sure the node has been set. + if (endpoint.getNode() == null) { + throw new GraphIOException( + "Element 'endpoint' is missing attribute 'node'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + endpoint.setDescription(desc); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this object. + applyKeys(endpoint); + + return endpoint; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.*; +import edu.uci.ics.jung.io.graphml.GraphMetadata.EdgeDefault; + +/** + * Parses graph elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class GraphElementParser,V,E> extends AbstractElementParser { + + public GraphElementParser(ParserContext parserContext) { + super(parserContext); + } + + public GraphMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new graph. + GraphMetadata graphMetadata = new GraphMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (graphMetadata.getId() == null + && GraphMLConstants.ID_NAME.equals(name)) { + + graphMetadata.setId(value); + } else if (graphMetadata.getEdgeDefault() == null + && GraphMLConstants.EDGEDEFAULT_NAME.equals(name)) { + + graphMetadata.setEdgeDefault(GraphMLConstants.DIRECTED_NAME + .equals(value) ? EdgeDefault.DIRECTED + : EdgeDefault.UNDIRECTED); + } else { + graphMetadata.setProperty(name, value); + } + } + + // Make sure the graphdefault has been set. + if (graphMetadata.getEdgeDefault() == null) { + throw new GraphIOException( + "Element 'graph' is missing attribute 'edgedefault'"); + } + + Map idToVertexMap = new HashMap(); + Collection edgeMetadata = new LinkedList(); + Collection hyperEdgeMetadata = new LinkedList(); + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if (GraphMLConstants.DESC_NAME.equals(name)) { + + // Parse the description and set it in the graph. + String desc = (String) getParser(name).parse( + xmlEventReader, element); + graphMetadata.setDescription(desc); + + } else if (GraphMLConstants.DATA_NAME.equals(name)) { + + // Parse the data element and store the property in the graph. + DataMetadata data = (DataMetadata) getParser(name).parse( + xmlEventReader, element); + graphMetadata.addData(data); + + } else if (GraphMLConstants.NODE_NAME.equals(name)) { + + // Parse the node metadata + NodeMetadata metadata = (NodeMetadata) getParser(name).parse( + xmlEventReader, element); + + // Create the vertex object and store it in the metadata + V vertex = getParserContext().createVertex(metadata); + metadata.setVertex(vertex); + idToVertexMap.put(metadata.getId(), vertex); + + // Add it to the graph + graphMetadata.addNodeMetadata(vertex, metadata); + + } else if (GraphMLConstants.EDGE_NAME.equals(name)) { + + // Parse the edge metadata + EdgeMetadata metadata = (EdgeMetadata) getParser(name).parse( + xmlEventReader, element); + + // Set the directed property if not overridden. + if (metadata.isDirected() == null) { + metadata.setDirected(graphMetadata.getEdgeDefault() == EdgeDefault.DIRECTED); + } + + // Create the edge object and store it in the metadata + E edge = getParserContext().createEdge(metadata); + edgeMetadata.add(metadata); + metadata.setEdge(edge); + + // Add it to the graph. + graphMetadata.addEdgeMetadata(edge, metadata); + + } else if (GraphMLConstants.HYPEREDGE_NAME.equals(name)) { + + // Parse the edge metadata + HyperEdgeMetadata metadata = (HyperEdgeMetadata) getParser(name).parse( + xmlEventReader, element); + + // Create the edge object and store it in the metadata + E edge = getParserContext().createHyperEdge(metadata); + hyperEdgeMetadata.add(metadata); + metadata.setEdge(edge); + + // Add it to the graph + graphMetadata.addHyperEdgeMetadata(edge, metadata); + + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this object. + applyKeys(graphMetadata); + + // Create the graph object and store it in the metadata + G graph = getParserContext().createGraph(graphMetadata); + graphMetadata.setGraph(graph); + + // Add all of the vertices to the graph object. + addVerticesToGraph(graph, idToVertexMap.values()); + + // Add the edges to the graph object. + addEdgesToGraph(graph, edgeMetadata, idToVertexMap); + addHyperEdgesToGraph(graph, hyperEdgeMetadata, idToVertexMap); + + return graphMetadata; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } + + private void addVerticesToGraph(G graph, Collection vertices) { + + for (V vertex : vertices) { + graph.addVertex(vertex); + } + } + + @SuppressWarnings("unchecked") + private void addEdgesToGraph(G graph, Collection metadata, + Map idToVertexMap) throws GraphIOException { + + for (EdgeMetadata emd : metadata) { + + // Get the edge out of the metadata + E edge = (E)emd.getEdge(); + + // Get the verticies. + V source = idToVertexMap.get(emd.getSource()); + V target = idToVertexMap.get(emd.getTarget()); + if (source == null || target == null) { + throw new GraphIOException( + "edge references undefined source or target vertex. " + + "Source: " + emd.getSource() + + ", Target: " + emd.getTarget()); + } + + // Add it to the graph. + if (graph instanceof Graph) { + ((Graph) graph).addEdge(edge, source, target, emd + .isDirected() ? EdgeType.DIRECTED + : EdgeType.UNDIRECTED); + } else { + graph.addEdge(edge, new Pair(source, target)); + } + } + } + + @SuppressWarnings("unchecked") + private void addHyperEdgesToGraph(G graph, Collection metadata, + Map idToVertexMap) throws GraphIOException { + + for (HyperEdgeMetadata emd : metadata) { + + // Get the edge out of the metadata + E edge = (E)emd.getEdge(); + + // Add the verticies to a list. + List verticies = new ArrayList(); + List endpoints = emd.getEndpoints(); + for (EndpointMetadata ep : endpoints) { + V v = idToVertexMap.get(ep.getNode()); + if (v == null) { + throw new GraphIOException( + "hyperedge references undefined vertex: " + + ep.getNode()); + } + verticies.add(v); + } + + // Add it to the graph. + graph.addEdge(edge, verticies); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphMLEventFilter.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphMLEventFilter.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphMLEventFilter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/GraphMLEventFilter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import javax.xml.stream.EventFilter; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.events.XMLEvent; + +/** + * Filter to ignore unsupported XML events. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class GraphMLEventFilter implements EventFilter { + + public boolean accept(XMLEvent event) { + switch( event.getEventType() ) { + case XMLStreamConstants.START_ELEMENT: + case XMLStreamConstants.END_ELEMENT: + case XMLStreamConstants.CHARACTERS: + case XMLStreamConstants.ATTRIBUTE: + case XMLStreamConstants.NAMESPACE: + case XMLStreamConstants.START_DOCUMENT: + case XMLStreamConstants.END_DOCUMENT: { + return true; + } + default: { + return false; + } + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/HyperEdgeElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/HyperEdgeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/HyperEdgeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/HyperEdgeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.*; + +/** + * Parses hyper edge elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class HyperEdgeElementParser,V,E> extends AbstractElementParser { + + public HyperEdgeElementParser(ParserContext parserContext) { + super(parserContext); + } + + public HyperEdgeMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new edge. + HyperEdgeMetadata edge = new HyperEdgeMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = (Attribute) iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (edge.getId() == null && GraphMLConstants.ID_NAME.equals(name)) { + edge.setId(value); + } else { + edge.setProperty(name, value); + } + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + edge.setDescription(desc); + } else if(GraphMLConstants.DATA_NAME.equals(name)) { + DataMetadata data = (DataMetadata)getParser(name).parse(xmlEventReader, element); + edge.addData(data); + } else if(GraphMLConstants.ENDPOINT_NAME.equals(name)) { + EndpointMetadata ep = (EndpointMetadata)getParser(name).parse(xmlEventReader, element); + edge.addEndpoint(ep); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this object. + applyKeys(edge); + + return edge; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/KeyElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/KeyElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/KeyElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/KeyElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.GraphMLConstants; +import edu.uci.ics.jung.io.graphml.Key; +import edu.uci.ics.jung.io.graphml.ExceptionConverter; + +/** + * Parses key elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class KeyElementParser,V,E> extends AbstractElementParser { + + public KeyElementParser(ParserContext parserContext) { + super(parserContext); + } + + public Key parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new key. ForType defaults to ALL. + Key key = new Key(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (key.getId() == null && GraphMLConstants.ID_NAME.equals(name)) { + key.setId(value); + } else if (key.getAttributeName() == null + && GraphMLConstants.ATTRNAME_NAME.equals(name)) { + key.setAttributeName(value); + } else if (key.getAttributeType() == null + && GraphMLConstants.ATTRTYPE_NAME.equals(name)) { + key.setAttributeType(value); + } else if (GraphMLConstants.FOR_NAME.equals(name)) { + key.setForType(convertFor(value)); + } + } + + // Make sure the id has been set. + if (key.getId() == null) { + throw new GraphIOException( + "Element 'key' is missing attribute 'id'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + key.setDescription(desc); + } else if(GraphMLConstants.DEFAULT_NAME.equals(name)) { + String defaultValue = (String)getParser(name).parse(xmlEventReader, element); + key.setDefaultValue(defaultValue); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + return key; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } + + static public Key.ForType convertFor(String value) { + + if (value != null) { + + if (GraphMLConstants.GRAPH_NAME.equals(value)) { + return Key.ForType.GRAPH; + } + if (GraphMLConstants.EDGE_NAME.equals(value)) { + return Key.ForType.EDGE; + } + if (GraphMLConstants.ENDPOINT_NAME.equals(value)) { + return Key.ForType.ENDPOINT; + } + if (GraphMLConstants.HYPEREDGE_NAME.equals(value)) { + return Key.ForType.HYPEREDGE; + } + if (GraphMLConstants.NODE_NAME.equals(value)) { + return Key.ForType.NODE; + } + if (GraphMLConstants.PORT_NAME.equals(value)) { + return Key.ForType.PORT; + } + } + + return Key.ForType.ALL; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/NodeElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/NodeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/NodeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/NodeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.*; + +/** + * Parses node elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class NodeElementParser,V,E> extends AbstractElementParser { + + public NodeElementParser(ParserContext parserContext) { + super(parserContext); + } + + @SuppressWarnings("unchecked") + public NodeMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + // Create the new node. + NodeMetadata node = new NodeMetadata(); + + // Parse the attributes. + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (node.getId() == null && GraphMLConstants.ID_NAME.equals(name)) { + node.setId(value); + } else { + node.setProperty(name, value); + } + } + + // Make sure the name has been set. + if (node.getId() == null) { + throw new GraphIOException( + "Element 'node' is missing attribute 'id'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + node.setDescription(desc); + } else if(GraphMLConstants.DATA_NAME.equals(name)) { + DataMetadata data = (DataMetadata)getParser(name).parse(xmlEventReader, element); + node.addData(data); + } else if(GraphMLConstants.PORT_NAME.equals(name)) { + PortMetadata port = (PortMetadata)getParser(name).parse(xmlEventReader, element); + node.addPort(port); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } else if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this object. + applyKeys(node); + + return node; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ParserContext.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ParserContext.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ParserContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/ParserContext.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.graphml.EdgeMetadata; +import edu.uci.ics.jung.io.graphml.GraphMetadata; +import edu.uci.ics.jung.io.graphml.HyperEdgeMetadata; +import edu.uci.ics.jung.io.graphml.KeyMap; +import edu.uci.ics.jung.io.graphml.NodeMetadata; + +/** + * Provides resources related to the current parsing context. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @param The graph type + * @param The vertex type + * @param The edge type + */ +public class ParserContext, V, E> { + + private final KeyMap keyMap; + private final ElementParserRegistry elementParserRegistry; + private final Function graphTransformer; + private final Function vertexTransformer; + private final Function edgeTransformer; + private final Function hyperEdgeTransformer; + + public ParserContext(ElementParserRegistry elementParserRegistry, + KeyMap keyMap, + Function graphTransformer, + Function vertexTransformer, + Function edgeTransformer, + Function hyperEdgeTransformer ) { + this.elementParserRegistry = elementParserRegistry; + this.keyMap = keyMap; + this.graphTransformer = graphTransformer; + this.vertexTransformer = vertexTransformer; + this.edgeTransformer = edgeTransformer; + this.hyperEdgeTransformer = hyperEdgeTransformer; + } + + public ElementParserRegistry getElementParserRegistry() { + return elementParserRegistry; + } + + public KeyMap getKeyMap() { + return keyMap; + } + + public G createGraph(GraphMetadata metadata) { + return graphTransformer.apply(metadata); + } + + public V createVertex(NodeMetadata metadata) { + return vertexTransformer.apply(metadata); + } + + public E createEdge(EdgeMetadata metadata) { + return edgeTransformer.apply(metadata); + } + + public E createHyperEdge(HyperEdgeMetadata metadata) { + return hyperEdgeTransformer.apply(metadata); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/PortElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/PortElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/PortElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/PortElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Iterator; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.*; + +/** + * Parses port elements. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class PortElementParser,V,E> extends AbstractElementParser { + + public PortElementParser(ParserContext parserContext) { + super(parserContext); + } + + public PortMetadata parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + + // Create the new port. + PortMetadata port = new PortMetadata(); + + // Parse the attributes. + @SuppressWarnings("unchecked") + Iterator iterator = start.getAttributes(); + while (iterator.hasNext()) { + Attribute attribute = iterator.next(); + String name = attribute.getName().getLocalPart(); + String value = attribute.getValue(); + if (port.getName() == null && GraphMLConstants.NAME_NAME.equals(name)) { + port.setName(value); + } else { + port.setProperty(name, value); + } + } + + // Make sure the name has been set. + if (port.getName() == null) { + throw new GraphIOException( + "Element 'port' is missing attribute 'name'"); + } + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + StartElement element = (StartElement) event; + + String name = element.getName().getLocalPart(); + if(GraphMLConstants.DESC_NAME.equals(name)) { + String desc = (String)getParser(name).parse(xmlEventReader, element); + port.setDescription(desc); + } else if(GraphMLConstants.DATA_NAME.equals(name)) { + DataMetadata data = (DataMetadata)getParser(name).parse(xmlEventReader, element); + port.addData(data); + } else { + + // Treat anything else as unknown + getUnknownParser().parse(xmlEventReader, element); + } + + } + if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } + } + + // Apply the keys to this port. + applyKeys(port); + + return port; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/StringElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/StringElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/StringElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/StringElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.ExceptionConverter; + +/** + * Parses an element that just contains text. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class StringElementParser,V,E> extends AbstractElementParser { + + public StringElementParser(ParserContext parserContext) { + super(parserContext); + } + + public String parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + String str = null; + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + + // Parse the unknown element. + getUnknownParser().parse(xmlEventReader, event + .asStartElement()); + } else if (event.isEndElement()) { + EndElement end = (EndElement) event; + verifyMatch(start, end); + break; + } else if (event.isCharacters()) { + Characters characters = (Characters) event; + str = characters.getData(); + } + } + + return str; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/UnknownElementParser.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/UnknownElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/UnknownElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/parser/UnknownElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.Stack; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.ExceptionConverter; + +/** + * Skips an entire unknown subtree of the XML + * + * @author Nathan Mittler - nathan.mittler@gmail.com + */ +public class UnknownElementParser implements ElementParser { + + /** + * Skips an entire subtree starting with the provided unknown element. + * + * @param xmlEventReader + * the event reader + * @param start + * the unknown element to be skipped. + * @return null + */ + public Object parse(XMLEventReader xmlEventReader, StartElement start) + throws GraphIOException { + + try { + Stack skippedElements = new Stack(); + skippedElements.add(start.getName().getLocalPart()); + + while (xmlEventReader.hasNext()) { + + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + + String name = event.asStartElement().getName() + .getLocalPart(); + + // Push the name of the unknown element. + skippedElements.push(name); + } + if (event.isEndElement()) { + + String name = event.asEndElement().getName() + .getLocalPart(); + + if (skippedElements.size() == 0 + || !skippedElements.peek().equals(name)) { + throw new GraphIOException( + "Failed parsing GraphML document - startTag/endTag mismatch"); + } + + // Pop the stack. + skippedElements.pop(); + if( skippedElements.isEmpty() ) { + break; + } + } + } + + return null; + + } catch (Exception e) { + ExceptionConverter.convert(e); + } + + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/PortMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/PortMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/PortMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/graphml/PortMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +/** + * Metadata structure for the 'port' GraphML element. + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class PortMetadata extends AbstractMetadata { + + private String name; + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String desc) { + this.description = desc; + } + + public MetadataType getMetadataType() { + return MetadataType.PORT; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLMetadata.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLMetadata.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLMetadata.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLMetadata.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Jun 30, 2008 + * + */ +package edu.uci.ics.jung.io; + +import com.google.common.base.Function; + +/** + * Maintains information relating to data for the specified type. + * This includes a Function from objects to their values, + * a default value, and a description. + */ +public class GraphMLMetadata +{ + /** + * The description of this data type. + */ + public String description; + + /** + * The default value for objects of this type. + */ + public String default_value; + + /** + * A Function mapping objects to string representations of their values. + */ + public Function transformer; + + /** + * Creates a new instance with the specified description, + * default value, and function. + * + * @param description a textual description of the object + * @param default_value the default value for the object, as a String + * @param function maps objects of this type to string representations + */ + public GraphMLMetadata(String description, String default_value, + Function function) + { + this.description = description; + this.transformer = function; + this.default_value = default_value; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLReader.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLReader.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLReader.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,831 @@ +/* + * Created on Sep 21, 2007 + * + * Copyright (c) 2007, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.DefaultHandler; + +import com.google.common.base.Supplier; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +import edu.uci.ics.jung.algorithms.util.MapSettableTransformer; +import edu.uci.ics.jung.algorithms.util.SettableTransformer; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Reads in data from a GraphML-formatted file and generates graphs based on + * that data. Currently supports the following parts of the GraphML + * specification: + *

      + *
    • graphs and hypergraphs + *
    • directed and undirected edges + *
    • graph, vertex, edge data + *
    • graph, vertex, edge descriptions and data descriptions + *
    • vertex and edge IDs + *
    + * Each of these is exposed via appropriate get methods. + * + * Does not currently support nested graphs or ports. + * + *

    Note that the user is responsible for supplying a graph + * Factory that can support the edge types in the supplied + * GraphML file. If the graph generated by the Factory is + * not compatible (for example: if the graph does not accept directed + * edges, and the GraphML file contains a directed edge) then the results + * are graph-implementation-dependent. + * + * @see "http://graphml.graphdrawing.org/specification.html" + */ +public class GraphMLReader, V, E> extends DefaultHandler +{ + protected enum TagState {NO_TAG, VERTEX, EDGE, HYPEREDGE, ENDPOINT, GRAPH, + DATA, KEY, DESC, DEFAULT_KEY, GRAPHML, OTHER} + + protected enum KeyType {NONE, VERTEX, EDGE, GRAPH, ALL} + + protected SAXParser saxp; + protected EdgeType default_edgetype; + protected G current_graph; + protected V current_vertex; + protected E current_edge; + protected String current_key; + protected LinkedList current_states; + protected BiMap tag_state; + protected Supplier graph_factory; + protected Supplier vertex_factory; + protected Supplier edge_factory; + protected BiMap vertex_ids; + protected BiMap edge_ids; + protected Map> graph_metadata; + protected Map> vertex_metadata; + protected Map> edge_metadata; + protected Map vertex_desc; + protected Map edge_desc; + protected Map graph_desc; + protected KeyType key_type; + protected Collection hyperedge_vertices; + + protected List graphs; + + protected StringBuilder current_text = new StringBuilder(); + + /** + * Creates a GraphMLReader instance with the specified + * vertex and edge factories. + * + * @param vertex_factory the vertex supplier to use to create vertex objects + * @param edge_factory the edge supplier to use to create edge objects + * @throws ParserConfigurationException if a SAX parser cannot be constructed + * @throws SAXException if the SAX parser factory cannot be constructed + */ + public GraphMLReader(Supplier vertex_factory, + Supplier edge_factory) + throws ParserConfigurationException, SAXException + { + current_vertex = null; + current_edge = null; + + SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); + saxp = saxParserFactory.newSAXParser(); + + current_states = new LinkedList(); + + tag_state = HashBiMap.create(); + tag_state.put("node", TagState.VERTEX); + tag_state.put("edge", TagState.EDGE); + tag_state.put("hyperedge", TagState.HYPEREDGE); + tag_state.put("endpoint", TagState.ENDPOINT); + tag_state.put("graph", TagState.GRAPH); + tag_state.put("data", TagState.DATA); + tag_state.put("key", TagState.KEY); + tag_state.put("desc", TagState.DESC); + tag_state.put("default", TagState.DEFAULT_KEY); + tag_state.put("graphml", TagState.GRAPHML); + + this.key_type = KeyType.NONE; + + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + } + + /** + * Creates a GraphMLReader instance that assigns the vertex + * and edge id strings to be the vertex and edge objects, + * as well as their IDs. + * Note that this requires that (a) each edge have a valid ID, which is not + * normally a requirement for edges in GraphML, and (b) that the vertex + * and edge types be assignment-compatible with String. + * @throws ParserConfigurationException if a SAX parser cannot be constructed + * @throws SAXException if the SAX parser factory cannot be constructed + */ + public GraphMLReader() throws ParserConfigurationException, SAXException + { + this(null, null); + } + + /** + * Returns a list of the graphs parsed from the specified reader, as created by + * the specified Supplier. + * @param reader the source of the graph data in GraphML format + * @param graph_factory used to build graph instances + * @return the graphs parsed from the specified reader + * @throws IOException if an error is encountered while parsing the graph + */ + public List loadMultiple(Reader reader, Supplier graph_factory) + throws IOException + { + this.graph_factory = graph_factory; + initializeData(); + clearData(); + parse(reader); + + return graphs; + } + + /** + * Returns a list of the graphs parsed from the specified file, as created by + * the specified Supplier. + * @param filename the source of the graph data in GraphML format + * @param graph_factory used to build graph instances + * @return the graphs parsed from the specified file + * @throws IOException if an error is encountered while parsing the graph + */ + public List loadMultiple(String filename, Supplier graph_factory) throws IOException + { + return loadMultiple(new FileReader(filename), graph_factory); + } + + /** + * Populates the specified graph with the data parsed from the reader. + * @param reader the source of the graph data in GraphML format + * @param g the graph instance to populate + * @throws IOException if an error is encountered while parsing the graph + */ + public void load(Reader reader, G g) throws IOException + { + this.current_graph = g; + this.graph_factory = null; + initializeData(); + clearData(); + + parse(reader); + } + + /** + * Populates the specified graph with the data parsed from the specified file. + * @param filename the source of the graph data in GraphML format + * @param g the graph instance to populate + * @throws IOException if an error is encountered while parsing the graph + */ + public void load(String filename, G g) throws IOException + { + load(new FileReader(filename), g); + } + + protected void clearData() + { + this.vertex_ids.clear(); + this.vertex_desc.clear(); + + this.edge_ids.clear(); + this.edge_desc.clear(); + + this.graph_desc.clear(); + + this.hyperedge_vertices.clear(); + } + + /** + * This is separate from initialize() because these data structures are shared among all + * graphs loaded (i.e., they're defined inside graphml rather than graph. + */ + protected void initializeData() + { + this.vertex_ids = HashBiMap.create(); + this.vertex_desc = new HashMap(); + this.vertex_metadata = new HashMap>(); + + this.edge_ids = HashBiMap.create(); + this.edge_desc = new HashMap(); + this.edge_metadata = new HashMap>(); + + this.graph_desc = new HashMap(); + this.graph_metadata = new HashMap>(); + + this.hyperedge_vertices = new ArrayList(); + } + + protected void parse(Reader reader) throws IOException + { + try + { + saxp.parse(new InputSource(reader), this); + reader.close(); + } + catch (SAXException saxe) + { + throw new IOException(saxe.getMessage()); + } + } + + @Override + public void startElement(String uri, String name, String qName, Attributes atts) throws SAXNotSupportedException + { + String tag = qName.toLowerCase(); + TagState state = tag_state.get(tag); + if (state == null) + state = TagState.OTHER; + + switch (state) + { + case GRAPHML: + break; + + case VERTEX: + if (this.current_graph == null) + throw new SAXNotSupportedException("Graph must be defined prior to elements"); + if (this.current_edge != null || this.current_vertex != null) + throw new SAXNotSupportedException("Nesting elements not supported"); + + createVertex(atts); + + break; + + case ENDPOINT: + if (this.current_graph == null) + throw new SAXNotSupportedException("Graph must be defined prior to elements"); + if (this.current_edge == null) + throw new SAXNotSupportedException("No edge defined for endpoint"); + if (this.current_states.getFirst() != TagState.HYPEREDGE) + throw new SAXNotSupportedException("Endpoints must be defined inside hyperedge"); + Map endpoint_atts = getAttributeMap(atts); + String node = endpoint_atts.remove("node"); + if (node == null) + throw new SAXNotSupportedException("Endpoint must include an 'id' attribute"); + V v = vertex_ids.inverse().get(node); + if (v == null) + throw new SAXNotSupportedException("Endpoint refers to nonexistent node ID: " + node); + + this.current_vertex = v; + hyperedge_vertices.add(v); + break; + + case EDGE: + case HYPEREDGE: + if (this.current_graph == null) + throw new SAXNotSupportedException("Graph must be defined prior to elements"); + if (this.current_edge != null || this.current_vertex != null) + throw new SAXNotSupportedException("Nesting elements not supported"); + + createEdge(atts, state); + break; + + case GRAPH: + if (this.current_graph != null && graph_factory != null) + throw new SAXNotSupportedException("Nesting graphs not currently supported"); + + // graph Supplier is null if there's only one graph + if (graph_factory != null) + current_graph = graph_factory.get(); + + // reset all non-key data structures (to avoid collisions between different graphs) + clearData(); + + // set up default direction of edges + Map graph_atts = getAttributeMap(atts); + String default_direction = graph_atts.remove("edgedefault"); + if (default_direction == null) + throw new SAXNotSupportedException("All graphs must specify a default edge direction"); + if (default_direction.equals("directed")) + this.default_edgetype = EdgeType.DIRECTED; + else if (default_direction.equals("undirected")) + this.default_edgetype = EdgeType.UNDIRECTED; + else + throw new SAXNotSupportedException("Invalid or unrecognized default edge direction: " + default_direction); + + // put remaining attribute/value pairs in graph_data + addExtraData(graph_atts, graph_metadata, current_graph); + + break; + + case DATA: + if (this.current_states.contains(TagState.DATA)) + throw new SAXNotSupportedException("Nested data not supported"); + handleData(atts); + break; + + case KEY: + createKey(atts); + break; + + + default: + break; + } + + current_states.addFirst(state); + } + + /** + * + * @param + * @param atts + * @param metadata_map + * @param current_elt + */ + private void addExtraData(Map atts, + Map> metadata_map, T current_elt) + { + // load in the default values; these override anything that might + // be in the attribute map (because that's not really a proper + // way to associate data) + for (Map.Entry> entry: metadata_map.entrySet()) + { + GraphMLMetadata gmlm = entry.getValue(); + if (gmlm.default_value != null) + { + SettableTransformer st = + (SettableTransformer)gmlm.transformer; + st.set(current_elt, gmlm.default_value); + } + } + + // place remaining items in data + for (Map.Entry entry : atts.entrySet()) + { + String key = entry.getKey(); + GraphMLMetadata key_data = metadata_map.get(key); + SettableTransformer st; + if (key_data != null) + { + // if there's a default value, don't override it + if (key_data.default_value != null) + continue; + st = (SettableTransformer)key_data.transformer; + } + else + { + st = new MapSettableTransformer( + new HashMap()); + key_data = new GraphMLMetadata(null, null, st); + metadata_map.put(key, key_data); + } + st.set(current_elt, entry.getValue()); + } + } + + + @Override + public void characters(char[] ch, int start, int length) throws SAXNotSupportedException + { + this.current_text.append(new String(ch, start, length)); + } + + + protected void addDatum(Map> metadata, + T current_elt, String text) throws SAXNotSupportedException + { + if (metadata.containsKey(this.current_key)) + { + SettableTransformer st = + (SettableTransformer)(metadata.get(this.current_key).transformer); + st.set(current_elt, text); + } + else + throw new SAXNotSupportedException("key " + this.current_key + + " not valid for element " + current_elt); + } + + @Override + public void endElement(String uri, String name, String qName) throws SAXNotSupportedException + { + String text = current_text.toString().trim(); + current_text.setLength(0); + + String tag = qName.toLowerCase(); + TagState state = tag_state.get(tag); + if (state == null) + state = TagState.OTHER; + if (state == TagState.OTHER) + return; + + if (state != current_states.getFirst()) + throw new SAXNotSupportedException("Unbalanced tags: opened " + + tag_state.inverse().get(current_states.getFirst()) + + ", closed " + tag); + + switch(state) + { + case VERTEX: + case ENDPOINT: + current_vertex = null; + break; + + case EDGE: + current_edge = null; + break; + + case HYPEREDGE: + current_graph.addEdge(current_edge, hyperedge_vertices); + hyperedge_vertices.clear(); + current_edge = null; + break; + + case GRAPH: + current_graph = null; + break; + + case KEY: + current_key = null; + break; + + case DESC: + switch (this.current_states.get(1)) // go back one + { + case GRAPH: + graph_desc.put(current_graph, text); + break; + case VERTEX: + case ENDPOINT: + vertex_desc.put(current_vertex, text); + break; + case EDGE: + case HYPEREDGE: + edge_desc.put(current_edge, text); + break; + case DATA: + switch (key_type) + { + case GRAPH: + graph_metadata.get(current_key).description = text; + break; + case VERTEX: + vertex_metadata.get(current_key).description = text; + break; + case EDGE: + edge_metadata.get(current_key).description = text; + break; + case ALL: + graph_metadata.get(current_key).description = text; + vertex_metadata.get(current_key).description = text; + edge_metadata.get(current_key).description = text; + break; + default: + throw new SAXNotSupportedException("Invalid key type" + + " specified for default: " + key_type); + } + + break; + default: + break; + } + break; + case DATA: + this.key_type = KeyType.NONE; + switch (this.current_states.get(1)) + { + case GRAPH: + addDatum(graph_metadata, current_graph, text); + break; + case VERTEX: + case ENDPOINT: + addDatum(vertex_metadata, current_vertex, text); + break; + case EDGE: + case HYPEREDGE: + addDatum(edge_metadata, current_edge, text); + break; + default: + break; + } + break; + case DEFAULT_KEY: + if (this.current_states.get(1) != TagState.KEY) + throw new SAXNotSupportedException("'default' only defined in context of 'key' tag: " + + "stack: " + current_states.toString()); + + switch (key_type) + { + case GRAPH: + graph_metadata.get(current_key).default_value = text; + break; + case VERTEX: + vertex_metadata.get(current_key).default_value = text; + break; + case EDGE: + edge_metadata.get(current_key).default_value = text; + break; + case ALL: + graph_metadata.get(current_key).default_value = text; + vertex_metadata.get(current_key).default_value = text; + edge_metadata.get(current_key).default_value = text; + break; + default: + throw new SAXNotSupportedException("Invalid key type" + + " specified for default: " + key_type); + } + + break; + default: + break; + } + + current_states.removeFirst(); + } + + protected Map getAttributeMap(Attributes atts) + { + Map att_map = new HashMap(); + for (int i = 0; i < atts.getLength(); i++) + att_map.put(atts.getQName(i), atts.getValue(i)); + + return att_map; + } + + protected void handleData(Attributes atts) throws SAXNotSupportedException + { + switch (this.current_states.getFirst()) + { + case GRAPH: + break; + case VERTEX: + case ENDPOINT: + break; + case EDGE: + break; + case HYPEREDGE: + break; + default: + throw new SAXNotSupportedException("'data' tag only defined " + + "if immediately containing tag is 'graph', 'node', " + + "'edge', or 'hyperedge'"); + } + this.current_key = getAttributeMap(atts).get("key"); + if (this.current_key == null) + throw new SAXNotSupportedException("'data' tag requires a key specification"); + if (this.current_key.equals("")) + throw new SAXNotSupportedException("'data' tag requires a non-empty key"); + if (!getGraphMetadata().containsKey(this.current_key) && + !getVertexMetadata().containsKey(this.current_key) && + !getEdgeMetadata().containsKey(this.current_key)) + { + throw new SAXNotSupportedException("'data' tag's key specification must reference a defined key"); + } + + } + + protected void createKey(Attributes atts) throws SAXNotSupportedException + { + Map key_atts = getAttributeMap(atts); + String id = key_atts.remove("id"); + String for_type = key_atts.remove("for"); + + if (for_type == null || for_type.equals("") || for_type.equals("all")) + { + vertex_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + edge_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + graph_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + key_type = KeyType.ALL; + } + else + { + TagState type = tag_state.get(for_type); + switch (type) + { + case VERTEX: + vertex_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + key_type = KeyType.VERTEX; + break; + case EDGE: + case HYPEREDGE: + edge_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + key_type = KeyType.EDGE; + break; + case GRAPH: + graph_metadata.put(id, + new GraphMLMetadata(null, null, + new MapSettableTransformer(new HashMap()))); + key_type = KeyType.GRAPH; + break; + default: + throw new SAXNotSupportedException( + "Invalid metadata target type: " + for_type); + } + } + + this.current_key = id; + + } + + @SuppressWarnings("unchecked") + protected void createVertex(Attributes atts) throws SAXNotSupportedException + { + Map vertex_atts = getAttributeMap(atts); + String id = vertex_atts.remove("id"); + if (id == null) + throw new SAXNotSupportedException("node attribute list missing " + + "'id': " + atts.toString()); + V v = vertex_ids.inverse().get(id); + + if (v == null) + { + if (vertex_factory != null) + v = vertex_factory.get(); + else + v = (V)id; + vertex_ids.put(v, id); + this.current_graph.addVertex(v); + + // put remaining attribute/value pairs in vertex_data + addExtraData(vertex_atts, vertex_metadata, v); + } + else + throw new SAXNotSupportedException("Node id \"" + id + + " is a duplicate of an existing node ID"); + + this.current_vertex = v; + } + + + @SuppressWarnings("unchecked") + protected void createEdge(Attributes atts, TagState state) + throws SAXNotSupportedException + { + Map edge_atts = getAttributeMap(atts); + + String id = edge_atts.remove("id"); + E e; + if (edge_factory != null) + e = edge_factory.get(); + else + if (id != null) + e = (E)id; + else + throw new IllegalArgumentException("If no edge Supplier is supplied, " + + "edge id may not be null: " + edge_atts); + + if (id != null) + { + if (edge_ids.containsKey(e)) + throw new SAXNotSupportedException("Edge id \"" + id + + "\" is a duplicate of an existing edge ID"); + edge_ids.put(e, id); + } + + if (state == TagState.EDGE) + assignEdgeSourceTarget(e, atts, edge_atts); //, id); + + // put remaining attribute/value pairs in edge_data + addExtraData(edge_atts, edge_metadata, e); + + this.current_edge = e; + } + + protected void assignEdgeSourceTarget(E e, Attributes atts, + Map edge_atts)//, String id) + throws SAXNotSupportedException + { + String source_id = edge_atts.remove("source"); + if (source_id == null) + throw new SAXNotSupportedException("edge attribute list missing " + + "'source': " + atts.toString()); + V source = vertex_ids.inverse().get(source_id); + if (source == null) + throw new SAXNotSupportedException("specified 'source' attribute " + + "\"" + source_id + "\" does not match any node ID"); + + String target_id = edge_atts.remove("target"); + if (target_id == null) + throw new SAXNotSupportedException("edge attribute list missing " + + "'target': " + atts.toString()); + V target = vertex_ids.inverse().get(target_id); + if (target == null) + throw new SAXNotSupportedException("specified 'target' attribute " + + "\"" + target_id + "\" does not match any node ID"); + + String directed = edge_atts.remove("directed"); + EdgeType edge_type; + if (directed == null) + edge_type = default_edgetype; + else if (directed.equals("true")) + edge_type = EdgeType.DIRECTED; + else if (directed.equals("false")) + edge_type = EdgeType.UNDIRECTED; + else + throw new SAXNotSupportedException("Unrecognized edge direction specifier 'direction=\"" + + directed + "\"': " + "source: " + source_id + ", target: " + target_id); + + if (current_graph instanceof Graph) + ((Graph)this.current_graph).addEdge(e, source, target, + edge_type); + else + this.current_graph.addEdge(e, new Pair(source, target)); + } + + /** + * @return a bidirectional map relating vertices and IDs. + */ + public BiMap getVertexIDs() + { + return vertex_ids; + } + + /** + * Returns a bidirectional map relating edges and IDs. + * This is not guaranteed to always be populated (edge IDs are not + * required in GraphML files. + * @return a bidirectional map relating edges and IDs. + */ + public BiMap getEdgeIDs() + { + return edge_ids; + } + + /** + * @return a map from graph type name to type metadata + */ + public Map> getGraphMetadata() + { + return graph_metadata; + } + + /** + * @return a map from vertex type name to type metadata + */ + public Map> getVertexMetadata() + { + return vertex_metadata; + } + + /** + * @return a map from edge type name to type metadata + */ + public Map> getEdgeMetadata() + { + return edge_metadata; + } + + /** + * @return a map from graphs to graph descriptions + */ + public Map getGraphDescriptions() + { + return graph_desc; + } + + /** + * @return a map from vertices to vertex descriptions + */ + public Map getVertexDescriptions() + { + return vertex_desc; + } + + /** + * @return a map from edges to edge descriptions + */ + public Map getEdgeDescriptions() + { + return edge_desc; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLWriter.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLWriter.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphMLWriter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,440 @@ +/* + * Created on June 16, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Writes graphs out in GraphML format. + * + * Current known issues: + *

      + *
    • Only supports one graph per output file. + *
    • Does not indent lines for text-format readability. + *
    + * + */ +public class GraphMLWriter +{ + protected Function vertex_ids; + protected Function edge_ids; + protected Map>> graph_data; + protected Map> vertex_data; + protected Map> edge_data; + protected Function vertex_desc; + protected Function edge_desc; + protected Function, String> graph_desc; + protected boolean directed; + protected int nest_level; + + public GraphMLWriter() + { + vertex_ids = new Function() + { + public String apply(V v) + { + return v.toString(); + } + }; + edge_ids = Functions.constant(null); + graph_data = Collections.emptyMap(); + vertex_data = Collections.emptyMap(); + edge_data = Collections.emptyMap(); + vertex_desc = Functions.constant(null); + edge_desc = Functions.constant(null); + graph_desc = Functions.constant(null); + nest_level = 0; + } + + + /** + * Writes {@code graph} out using {@code w}. + * @param graph the graph to write out + * @param w the writer instance to which the graph data will be written out + * @throws IOException if writing the graph fails + */ + public void save(Hypergraph graph, Writer w) throws IOException + { + BufferedWriter bw = new BufferedWriter(w); + + // write out boilerplate header + bw.write("\n"); + bw.write("\n"); + + // write out data specifiers, including defaults + for (String key : graph_data.keySet()) + writeKeySpecification(key, "graph", graph_data.get(key), bw); + for (String key : vertex_data.keySet()) + writeKeySpecification(key, "node", vertex_data.get(key), bw); + for (String key : edge_data.keySet()) + writeKeySpecification(key, "edge", edge_data.get(key), bw); + + // write out graph-level information + // set edge default direction + bw.write("\n"); + else + bw.write("undirected\">\n"); + + // write graph description, if any + String desc = graph_desc.apply(graph); + if (desc != null) + bw.write("" + desc + "\n"); + + // write graph data out if any + for (String key : graph_data.keySet()) + { + Function, ?> t = graph_data.get(key).transformer; + Object value = t.apply(graph); + if (value != null) + bw.write(format("data", "key", key, value.toString()) + "\n"); + } + + // write vertex information + writeVertexData(graph, bw); + + // write edge information + writeEdgeData(graph, bw); + + // close graph + bw.write("\n"); + bw.write("\n"); + bw.flush(); + + bw.close(); + } + +// public boolean save(Collection> graphs, Writer w) +// { +// return true; +// } + + protected void writeIndentedText(BufferedWriter w, String to_write) throws IOException + { + for (int i = 0; i < nest_level; i++) + w.write(" "); + w.write(to_write); + } + + protected void writeVertexData(Hypergraph graph, BufferedWriter w) throws IOException + { + for (V v: graph.getVertices()) + { + String v_string = String.format("\n"); + closed = true; + w.write("" + desc + "\n"); + } + // write data out if any + for (String key : vertex_data.keySet()) + { + Function t = vertex_data.get(key).transformer; + if (t != null) + { + Object value = t.apply(v); + if (value != null) + { + if (!closed) + { + w.write(v_string + ">\n"); + closed = true; + } + w.write(format("data", "key", key, value.toString()) + "\n"); + } + } + } + if (!closed) + w.write(v_string + "/>\n"); // no contents; close the node with "/>" + else + w.write("\n"); + } + } + + protected void writeEdgeData(Hypergraph g, Writer w) throws IOException + { + for (E e: g.getEdges()) + { + Collection vertices = g.getIncidentVertices(e); + String id = edge_ids.apply(e); + String e_string; + boolean is_hyperedge = !(g instanceof Graph); + if (is_hyperedge) + { + e_string = " endpoints = new Pair(vertices); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + e_string = "\n"); + closed = true; + w.write("" + desc + "\n"); + } + // write data out if any + for (String key : edge_data.keySet()) + { + Function t = edge_data.get(key).transformer; + Object value = t.apply(e); + if (value != null) + { + if (!closed) + { + w.write(e_string + ">\n"); + closed = true; + } + w.write(format("data", "key", key, value.toString()) + "\n"); + } + } + // if this is a hyperedge, write endpoints out if any + if (is_hyperedge) + { + for (V v : vertices) + { + if (!closed) + { + w.write(e_string + ">\n"); + closed = true; + } + w.write("\n"); + } + } + + if (!closed) + w.write(e_string + "/>\n"); // no contents; close the edge with "/>" + else + if (is_hyperedge) + w.write("\n"); + else + w.write("\n"); + } + } + + protected void writeKeySpecification(String key, String type, + GraphMLMetadata ds, BufferedWriter bw) throws IOException + { + bw.write("\n"); + closed = true; + } + bw.write("" + desc + "\n"); + } + // write out default if any + Object def = ds.default_value; + if (def != null) + { + if (!closed) + { + bw.write(">\n"); + closed = true; + } + bw.write("" + def.toString() + "\n"); + } + if (!closed) + bw.write("/>\n"); + else + bw.write("\n"); + } + + protected String format(String type, String attr, String value, String contents) + { + return String.format("<%s %s=\"%s\">%s", + type, attr, value, contents, type); + } + + /** + * Provides an ID that will be used to identify a vertex in the output file. + * If the vertex IDs are not set, the ID for each vertex will default to + * the output of toString + * (and thus not guaranteed to be unique). + * + * @param vertex_ids a mapping from vertex to ID + */ + public void setVertexIDs(Function vertex_ids) + { + this.vertex_ids = vertex_ids; + } + + + /** + * Provides an ID that will be used to identify an edge in the output file. + * If any edge ID is missing, no ID will be written out for the + * corresponding edge. + * + * @param edge_ids a mapping from edge to ID + */ + public void setEdgeIDs(Function edge_ids) + { + this.edge_ids = edge_ids; + } + + /** + * Provides a map from data type name to graph data. + * + * @param graph_map map from data type name to graph data + */ + public void setGraphData(Map>> graph_map) + { + graph_data = graph_map; + } + + /** + * Provides a map from data type name to vertex data. + * + * @param vertex_map map from data type name to vertex data + */ + public void setVertexData(Map> vertex_map) + { + vertex_data = vertex_map; + } + + /** + * Provides a map from data type name to edge data. + * + * @param edge_map map from data type name to edge data + */ + public void setEdgeData(Map> edge_map) + { + edge_data = edge_map; + } + + /** + * Adds a new graph data specification. + * + * @param id the ID of the data to add + * @param description a description of the data to add + * @param default_value a default value for the data type + * @param graph_transformer a mapping from graphs to their string representations + */ + public void addGraphData(String id, String description, String default_value, + Function, String> graph_transformer) + { + if (graph_data.equals(Collections.EMPTY_MAP)) + graph_data = new HashMap>>(); + graph_data.put(id, new GraphMLMetadata>(description, + default_value, graph_transformer)); + } + + /** + * Adds a new vertex data specification. + * + * @param id the ID of the data to add + * @param description a description of the data to add + * @param default_value a default value for the data type + * @param vertex_transformer a mapping from vertices to their string representations + */ + public void addVertexData(String id, String description, String default_value, + Function vertex_transformer) + { + if (vertex_data.equals(Collections.EMPTY_MAP)) + vertex_data = new HashMap>(); + vertex_data.put(id, new GraphMLMetadata(description, default_value, + vertex_transformer)); + } + + /** + * Adds a new edge data specification. + * + * @param id the ID of the data to add + * @param description a description of the data to add + * @param default_value a default value for the data type + * @param edge_transformer a mapping from edges to their string representations + */ + public void addEdgeData(String id, String description, String default_value, + Function edge_transformer) + { + if (edge_data.equals(Collections.EMPTY_MAP)) + edge_data = new HashMap>(); + edge_data.put(id, new GraphMLMetadata(description, default_value, + edge_transformer)); + } + + /** + * Provides vertex descriptions. + * @param vertex_desc a mapping from vertices to their descriptions + */ + public void setVertexDescriptions(Function vertex_desc) + { + this.vertex_desc = vertex_desc; + } + + /** + * Provides edge descriptions. + * @param edge_desc a mapping from edges to their descriptions + */ + public void setEdgeDescriptions(Function edge_desc) + { + this.edge_desc = edge_desc; + } + + /** + * Provides graph descriptions. + * @param graph_desc a mapping from graphs to their descriptions + */ + public void setGraphDescriptions(Function, String> graph_desc) + { + this.graph_desc = graph_desc; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphReader.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphReader.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/GraphReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/GraphReader.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io; + +import edu.uci.ics.jung.graph.Hypergraph; + +/** + * Interface for a reader of graph objects + * + * @author Nathan Mittler - nathan.mittler@gmail.com + * + * @param + * the graph type + * @param the vertex type + * the vertex type + * @param the edge type + * the edge type + */ +public interface GraphReader, V, E> { + + /** + * Reads a single graph object, if one is available. + * + * @return the next graph object, or null if none exists. + * @throws GraphIOException + * thrown if an error occurred. + */ + G readGraph() throws GraphIOException; + + /** + * Closes this resource and frees any resources. + * + * @throws GraphIOException + * thrown if an error occurred. + */ + void close() throws GraphIOException; +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/package.html libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/package.html --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,24 @@ + + + + + + + +

    Interfaces and classes for reading and writing graphs in various (file) +formats. Current formats fully or partially supported include: +

      +
    • GraphML format +
    • Pajek NET format +
    + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetReader.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,532 @@ +/* + * Created on May 3, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.awt.geom.Point2D; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.StringTokenizer; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.util.MapSettableTransformer; +import edu.uci.ics.jung.algorithms.util.SettableTransformer; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; + + +/** + * Reads a Graph from a Pajek NET formatted source. + * + *

    If the edge constraints specify that the graph is strictly undirected, + * and an "*Arcs" section is encountered, or if the edge constraints specify that the + * graph is strictly directed, and an "*Edges" section is encountered, + * an IllegalArgumentException is thrown. + * + *

    If the edge constraints do not permit parallel edges, only the first encountered + * of a set of parallel edges will be read; subsequent edges in that set will be ignored. + * + *

    More restrictive edge constraints will cause vertices to be generated + * that are more time- and space-efficient. + * + * At the moment, only supports the + * part of the specification that defines: + *

      + *
    • vertex ids (each must have a value from 1 to n, where n is the number of vertices) + *
    • vertex labels (must be in quotes if interrupted by whitespace) + *
    • directed edge connections (single or list) + *
    • undirected edge connections (single or list) + *
    • edge weights (not compatible with edges specified in list form) + *
      note: this version of PajekNetReader does not support multiple edge + * weights, as PajekNetFile does; this behavior is consistent with the NET format. + *
    • vertex locations (x and y; z coordinate is ignored) + *

    + * + * Here is an example format for a directed graph without edge weights + * and edges specified in list form:
    + *

    + * *vertices [# of vertices] 
    + * 1 "a" 
    + * 2 "b" 
    + * 3 "c" 
    + * *arcslist 
    + * 1 2 3 
    + * 2 3  
    + * 
    + * + * Here is an example format for an undirected graph with edge weights + * and edges specified in non-list form:
    + *
    + * *vertices [# of vertices] 
    + * 1 "a" 
    + * 2 "b" 
    + * 3 "c" 
    + * *edges 
    + * 1 2 0.1 
    + * 1 3 0.9 
    + * 2 3 1.0 
    + * 
    + * + * @author Joshua O'Madadhain + * @see "'Pajek - Program for Analysis and Visualization of Large Networks', Vladimir Batagelj and Andrej Mrvar, http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/pajekman.pdf" + * @author Tom Nelson - converted to jung2 + */ +public class PajekNetReader,V,E> +{ + protected Supplier vertex_factory; + protected Supplier edge_factory; + + /** + * The map for vertex labels (if any) created by this class. + */ + protected SettableTransformer vertex_labels = new MapSettableTransformer(new HashMap()); + + /** + * The map for vertex locations (if any) defined by this class. + */ + protected SettableTransformer vertex_locations = new MapSettableTransformer(new HashMap()); + + protected SettableTransformer edge_weights = + new MapSettableTransformer(new HashMap()); + + /** + * Used to specify whether the most recently read line is a + * Pajek-specific tag. + */ + private static final Predicate v_pred = new StartsWithPredicate("*vertices"); + private static final Predicate a_pred = new StartsWithPredicate("*arcs"); + private static final Predicate e_pred = new StartsWithPredicate("*edges"); + private static final Predicate t_pred = new StartsWithPredicate("*"); + private static final Predicate c_pred = Predicates.or(a_pred, e_pred); + protected static final Predicate l_pred = ListTagPred.getInstance(); + + /** + * Creates a PajekNetReader instance with the specified vertex and edge factories. + * @param vertex_factory the Supplier to use to create vertex objects + * @param edge_factory the Supplier to use to create edge objects + */ + public PajekNetReader(Supplier vertex_factory, Supplier edge_factory) + { + this.vertex_factory = vertex_factory; + this.edge_factory = edge_factory; + } + + /** + * Creates a PajekNetReader instance with the specified edge Supplier, + * and whose vertex objects correspond to the integer IDs assigned in the file. + * Note that this requires V to be assignment-compatible with + * an Integer value. + * @param edge_factory the Supplier to use to create edge objects + */ + public PajekNetReader(Supplier edge_factory) + { + this(null, edge_factory); + } + + /** + * Returns the graph created by parsing the specified file, as created + * by the specified Supplier. + * @param filename the file from which the graph is to be read + * @param graph_factory used to provide a graph instance + * @return a graph parsed from the specified file + * @throws IOException if the graph cannot be loaded + */ + public G load(String filename, Supplier graph_factory) throws IOException + { + return load(new FileReader(filename), graph_factory.get()); + } + + /** + * Returns the graph created by parsing the specified reader, as created + * by the specified Supplier. + * @param reader the reader instance from which the graph is to be read + * @param graph_factory used to provide a graph instance + * @return a graph parsed from the specified reader + * @throws IOException if the graph cannot be loaded + */ + public G load(Reader reader, Supplier graph_factory) throws IOException + { + return load(reader, graph_factory.get()); + } + + /** + * Returns the graph created by parsing the specified file, by populating the + * specified graph. + * @param filename the file from which the graph is to be read + * @param g the graph instance to populate + * @return a graph parsed from the specified file + * @throws IOException if the graph cannot be loaded + */ + public G load(String filename, G g) throws IOException + { + if (g == null) + throw new IllegalArgumentException("Graph provided must be non-null"); + return load(new FileReader(filename), g); + } + + /** + * Populates the graph g with the graph represented by the + * Pajek-format data supplied by reader. Stores edge weights, + * if any, according to nev (if non-null). + * + *

    Any existing vertices/edges of g, if any, are unaffected. + * + *

    The edge data are filtered according to g's constraints, if any; thus, if + * g only accepts directed edges, any undirected edges in the + * input are ignored. + * + * @param reader the reader from which the graph is to be read + * @param g the graph instance to populate + * @return a graph parsed from the specified reader + * @throws IOException if the graph cannot be loaded + */ + public G load(Reader reader, G g) throws IOException + { + BufferedReader br = new BufferedReader(reader); + + // ignore everything until we see '*Vertices' + String curLine = skip(br, v_pred); + + if (curLine == null) // no vertices in the graph; return empty graph + return g; + + // create appropriate number of vertices + StringTokenizer st = new StringTokenizer(curLine); + st.nextToken(); // skip past "*vertices"; + int num_vertices = Integer.parseInt(st.nextToken()); + List id = null; + if (vertex_factory != null) + { + for (int i = 1; i <= num_vertices; i++) + g.addVertex(vertex_factory.get()); + id = new ArrayList(g.getVertices()); + } + + // read vertices until we see any Pajek format tag ('*...') + curLine = null; + while (br.ready()) + { + curLine = br.readLine(); + if (curLine == null || t_pred.apply(curLine)) + break; + if (curLine == "") // skip blank lines + continue; + + try + { + readVertex(curLine, id, num_vertices); + } + catch (IllegalArgumentException iae) + { + br.close(); + reader.close(); + throw iae; + } + } + + // skip over the intermediate stuff (if any) + // and read the next arcs/edges section that we find + curLine = readArcsOrEdges(curLine, br, g, id, edge_factory); + + // ditto + readArcsOrEdges(curLine, br, g, id, edge_factory); + + br.close(); + reader.close(); + + return g; + } + + /** + * Parses curLine as a reference to a vertex, and optionally assigns + * label and location information. + */ + @SuppressWarnings("unchecked") + private void readVertex(String curLine, List id, int num_vertices) + { + V v; + String[] parts = null; + int coord_idx = -1; // index of first coordinate in parts; -1 indicates no coordinates found + String index; + String label = null; + // if there are quote marks on this line, split on them; label is surrounded by them + if (curLine.indexOf('"') != -1) + { + String[] initial_split = curLine.trim().split("\""); + // if there are any quote marks, there should be exactly 2 + if (initial_split.length < 2 || initial_split.length > 3) + throw new IllegalArgumentException("Unbalanced (or too many) " + + "quote marks in " + curLine); + index = initial_split[0].trim(); + label = initial_split[1].trim(); + if (initial_split.length == 3) + parts = initial_split[2].trim().split("\\s+", -1); + coord_idx = 0; + } + else // no quote marks, but are there coordinates? + { + parts = curLine.trim().split("\\s+", -1); + index = parts[0]; + switch (parts.length) + { + case 1: // just the ID; nothing to do, continue + break; + case 2: // just the ID and a label + label = parts[1]; + break; + case 3: // ID, no label, coordinates + coord_idx = 1; + break; + default: // ID, label, (x,y) coordinates, maybe some other stuff + coord_idx = 2; + break; + } + } + int v_id = Integer.parseInt(index) - 1; // go from 1-based to 0-based index + if (v_id >= num_vertices || v_id < 0) + throw new IllegalArgumentException("Vertex number " + v_id + + "is not in the range [1," + num_vertices + "]"); + if (id != null) + v = id.get(v_id); + else + v = (V)(new Integer(v_id)); + // only attach the label if there's one to attach + if (label != null && label.length() > 0 && vertex_labels != null) + vertex_labels.set(v, label); + + // parse the rest of the line + if (coord_idx != -1 && parts != null && parts.length >= coord_idx+2 && vertex_locations != null) + { + double x = Double.parseDouble(parts[coord_idx]); + double y = Double.parseDouble(parts[coord_idx+1]); + vertex_locations.set(v, new Point2D.Double(x,y)); + } + } + + + + @SuppressWarnings("unchecked") + private String readArcsOrEdges(String curLine, BufferedReader br, Graph g, List id, Supplier edge_factory) + throws IOException + { + String nextLine = curLine; + + // in case we're not there yet (i.e., format tag isn't arcs or edges) + if (! c_pred.apply(curLine)) + nextLine = skip(br, c_pred); + + boolean reading_arcs = false; + boolean reading_edges = false; + EdgeType directedness = null; + if (a_pred.apply(nextLine)) + { + if (g instanceof UndirectedGraph) { + throw new IllegalArgumentException("Supplied undirected-only graph cannot be populated with directed edges"); + } else { + reading_arcs = true; + directedness = EdgeType.DIRECTED; + } + } + if (e_pred.apply(nextLine)) + { + if (g instanceof DirectedGraph) + throw new IllegalArgumentException("Supplied directed-only graph cannot be populated with undirected edges"); + else + reading_edges = true; + directedness = EdgeType.UNDIRECTED; + } + + if (!(reading_arcs || reading_edges)) + return nextLine; + + boolean is_list = l_pred.apply(nextLine); + + while (br.ready()) + { + nextLine = br.readLine(); + if (nextLine == null || t_pred.apply(nextLine)) + break; + if (curLine == "") // skip blank lines + continue; + + StringTokenizer st = new StringTokenizer(nextLine.trim()); + + int vid1 = Integer.parseInt(st.nextToken()) - 1; + V v1; + if (id != null) + v1 = id.get(vid1); + else + v1 = (V)new Integer(vid1); + + + if (is_list) // one source, multiple destinations + { + do + { + createAddEdge(st, v1, directedness, g, id, edge_factory); + } while (st.hasMoreTokens()); + } + else // one source, one destination, at most one weight + { + E e = createAddEdge(st, v1, directedness, g, id, edge_factory); + // get the edge weight if we care + if (edge_weights != null && st.hasMoreTokens()) + edge_weights.set(e, new Float(st.nextToken())); + } + } + return nextLine; + } + + @SuppressWarnings("unchecked") + protected E createAddEdge(StringTokenizer st, V v1, + EdgeType directed, Graph g, List id, Supplier edge_factory) + { + int vid2 = Integer.parseInt(st.nextToken()) - 1; + V v2; + if (id != null) + v2 = id.get(vid2); + else + v2 = (V)new Integer(vid2); + E e = edge_factory.get(); + + // don't error-check this: let the graph implementation do whatever it's going to do + // (add the edge, replace the existing edge, throw an exception--depends on the graph implementation) + g.addEdge(e, v1, v2, directed); + return e; + } + + /** + * Returns the first line read from br for which p + * returns true, or null if there is no + * such line. + * @param br the reader from which the graph is being read + * @param p predicate specifying what line to accept + * @return the first line from {@code br} that matches {@code p}, or null + * @throws IOException if an error is encountered while reading from {@code br} + */ + protected String skip(BufferedReader br, Predicate p) throws IOException + { + while (br.ready()) + { + String curLine = br.readLine(); + if (curLine == null) + break; + curLine = curLine.trim(); + if (p.apply(curLine)) + return curLine; + } + return null; + } + + /** + * A Predicate which evaluates to true if the + * argument starts with the constructor-specified String. + * + * @author Joshua O'Madadhain + */ + protected static class StartsWithPredicate implements Predicate { + private String tag; + + protected StartsWithPredicate(String s) { + this.tag = s; + } + + public boolean apply(String str) { + return (str != null && str.toLowerCase().startsWith(tag)); + } + } + + + /** + * A Predicate which evaluates to true if the + * argument ends with the string "list". + * + * @author Joshua O'Madadhain + */ + protected static class ListTagPred implements Predicate + { + protected static ListTagPred instance; + + protected ListTagPred() {} + + protected static ListTagPred getInstance() + { + if (instance == null) + instance = new ListTagPred(); + return instance; + } + + public boolean apply(String s) + { + return (s != null && s.toLowerCase().endsWith("list")); + } + } + + /** + * @return the vertexLocationTransformer + */ + public SettableTransformer getVertexLocationTransformer() { + return vertex_locations; + } + + /** + * Provides a Function which will be used to write out the vertex locations. + * @param vertex_locations a container for the vertex locations + */ + public void setVertexLocationTransformer(SettableTransformer vertex_locations) + { + this.vertex_locations = vertex_locations; + } + + /** + * @return a mapping from vertices to their labels + */ + public SettableTransformer getVertexLabeller() { + return vertex_labels; + } + + /** + * Provides a Function which will be used to write out the vertex labels. + * @param vertex_labels a container for the vertex labels + */ + public void setVertexLabeller(SettableTransformer vertex_labels) + { + this.vertex_labels = vertex_labels; + } + + /** + * @return a mapping from edges to their weights + */ + public SettableTransformer getEdgeWeightTransformer() + { + return edge_weights; + } + + /** + * Provides a Function which will be used to write out edge weights. + * @param edge_weights a container for the edge weights + */ + public void setEdgeWeightTransformer(SettableTransformer edge_weights) + { + this.edge_weights = edge_weights; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetWriter.java libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetWriter.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/main/java/edu/uci/ics/jung/io/PajekNetWriter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * Created on May 4, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.awt.geom.Point2D; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * Writes graphs in the Pajek NET format. + * + *

    Labels for vertices, edge weights, and vertex locations may each optionally + * be specified. Note that vertex location coordinates + * must be normalized to the interval [0, 1] on each axis in order to conform to the + * Pajek specification. + * + * @author Joshua O'Madadhain + * @author Tom Nelson - converted to jung2 + */ +public class PajekNetWriter +{ + /** + * Creates a new instance. + */ + public PajekNetWriter() + { + } + + /** + * Saves the graph to the specified file. + * @param g the graph to be saved + * @param filename the filename of the file to write the graph to + * @param vs mapping from vertices to labels + * @param nev mapping from edges to weights + * @param vld mapping from vertices to locations + * @throws IOException if the graph cannot be saved + */ + public void save(Graph g, String filename, Function vs, + Function nev, Function vld) throws IOException + { + save(g, new FileWriter(filename), vs, nev, vld); + } + + /** + * Saves the graph to the specified file. + * @param g the graph to be saved + * @param filename the filename of the file to write the graph to + * @param vs mapping from vertices to labels + * @param nev mapping from edges to weights + * @throws IOException if the graph cannot be saved + */ + public void save(Graph g, String filename, Function vs, + Function nev) throws IOException + { + save(g, new FileWriter(filename), vs, nev, null); + } + + /** + * Saves the graph to the specified file. No vertex labels are written, and the + * edge weights are written as 1.0. + * @param g the graph to be saved + * @param filename the filename of the file to write the graph to + * @throws IOException if the graph cannot be saved + */ + public void save(Graph g, String filename) throws IOException + { + save(g, filename, null, null, null); + } + + /** + * Saves the graph to the specified writer. No vertex labels are written, and the + * edge weights are written as 1.0. + * @param g the graph to be saved + * @param w the writer instance to write the graph to + * @throws IOException if the graph cannot be saved + */ + public void save(Graph g, Writer w) throws IOException + { + save(g, w, null, null, null); + } + + /** + * Saves the graph to the specified writer. + * @param g the graph to be saved + * @param w the writer instance to write the graph to + * @param vs mapping from vertices to labels + * @param nev mapping from edges to weights + * @throws IOException if the graph cannot be saved + */ + public void save(Graph g, Writer w, Function vs, + Function nev) throws IOException + { + save(g, w, vs, nev, null); + } + + /** + * Saves the graph to the specified writer. + * @param graph the graph to be saved + * @param w the writer instance to write the graph to + * @param vs mapping from vertices to labels (no labels are written if null) + * @param nev mapping from edges to weights (defaults to weights of 1.0 if null) + * @param vld mapping from vertices to locations (no locations are written if null) + * @throws IOException if the graph cannot be saved + */ + public void save(Graph graph, Writer w, Function vs, + Function nev, Function vld) throws IOException + { + /* + * TODO: Changes we might want to make: + * - optionally writing out in list form + */ + + BufferedWriter writer = new BufferedWriter(w); + if (nev == null) + nev = new Function() { public Number apply(E e) { return 1; } }; + writer.write("*Vertices " + graph.getVertexCount()); + writer.newLine(); + + List id = new ArrayList(graph.getVertices()); + for (V currentVertex : graph.getVertices()) + { + // convert from 0-based to 1-based index + int v_id = id.indexOf(currentVertex) + 1; + writer.write(""+v_id); + if (vs != null) + { + String label = vs.apply(currentVertex); + if (label != null) + writer.write (" \"" + label + "\""); + } + if (vld != null) + { + Point2D location = vld.apply(currentVertex); + if (location != null) + writer.write (" " + location.getX() + " " + location.getY() + " 0.0"); + } + writer.newLine(); + } + + Collection d_set = new HashSet(); + Collection u_set = new HashSet(); + + boolean directed = graph instanceof DirectedGraph; + + boolean undirected = graph instanceof UndirectedGraph; + + // if it's strictly one or the other, no need to create extra sets + if (directed) + d_set.addAll(graph.getEdges()); + if (undirected) + u_set.addAll(graph.getEdges()); + if (!directed && !undirected) // mixed-mode graph + { + u_set.addAll(graph.getEdges()); + d_set.addAll(graph.getEdges()); + for(E e : graph.getEdges()) { + if(graph.getEdgeType(e) == EdgeType.UNDIRECTED) { + d_set.remove(e); + } else { + u_set.remove(e); + } + } + } + + // write out directed edges + if (!d_set.isEmpty()) + { + writer.write("*Arcs"); + writer.newLine(); + } + for (E e : d_set) + { + int source_id = id.indexOf(graph.getEndpoints(e).getFirst()) + 1; + int target_id = id.indexOf(graph.getEndpoints(e).getSecond()) + 1; + float weight = nev.apply(e).floatValue(); + writer.write(source_id + " " + target_id + " " + weight); + writer.newLine(); + } + + // write out undirected edges + if (!u_set.isEmpty()) + { + writer.write("*Edges"); + writer.newLine(); + } + for (E e : u_set) + { + Pair endpoints = graph.getEndpoints(e); + int v1_id = id.indexOf(endpoints.getFirst()) + 1; + int v2_id = id.indexOf(endpoints.getSecond()) + 1; + float weight = nev.apply(e).floatValue(); + writer.write(v1_id + " " + v2_id + " " + weight); + writer.newLine(); + } + writer.close(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/site/site.xml libjung-free-java-2.1.1/jung-io/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-io/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + +

    + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyEdge.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyEdge.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyEdge.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyEdge.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ +package edu.uci.ics.jung.io.graphml; + +import com.google.common.base.Function; + +public class DummyEdge extends DummyGraphObjectBase { + + public static class EdgeFactory implements Function { + int n = 100; + + public DummyEdge apply(EdgeMetadata md) { + return new DummyEdge(n++); + } + } + + public static class HyperEdgeFactory implements Function { + int n = 0; + + public DummyEdge apply(HyperEdgeMetadata md) { + return new DummyEdge(n++); + } + } + + public DummyEdge() { + } + + public DummyEdge(int v) { + super(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyGraphObjectBase.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyGraphObjectBase.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyGraphObjectBase.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyGraphObjectBase.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,53 @@ +package edu.uci.ics.jung.io.graphml; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.SetHypergraph; +import edu.uci.ics.jung.graph.UndirectedSparseGraph; + +public class DummyGraphObjectBase { + + public static class UndirectedSparseGraphFactory implements Function> { + + public Hypergraph apply(GraphMetadata arg0) { + return new UndirectedSparseGraph(); + } + } + + public static class SetHypergraphFactory implements Function> { + + public Hypergraph apply(GraphMetadata arg0) { + return new SetHypergraph(); + } + } + + public int myValue; + + public DummyGraphObjectBase() { + } + + public DummyGraphObjectBase(int v) { + myValue = v; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + myValue; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DummyGraphObjectBase other = (DummyGraphObjectBase) obj; + return myValue == other.myValue; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyVertex.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyVertex.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyVertex.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/DummyVertex.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,21 @@ +package edu.uci.ics.jung.io.graphml; + +import com.google.common.base.Function; + +public class DummyVertex extends DummyGraphObjectBase { + + public static class Factory implements Function { + int n = 0; + + public DummyVertex apply(NodeMetadata md) { + return new DummyVertex(n++); + } + } + + public DummyVertex() { + } + + public DummyVertex(int v) { + super(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/AbstractParserTest.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/AbstractParserTest.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/AbstractParserTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/AbstractParserTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.io.Reader; +import java.io.StringReader; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.After; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.io.graphml.DummyEdge; +import edu.uci.ics.jung.io.graphml.DummyGraphObjectBase; +import edu.uci.ics.jung.io.graphml.KeyMap; +import edu.uci.ics.jung.io.graphml.DummyVertex; + +public abstract class AbstractParserTest { + + + private ElementParserRegistry,DummyVertex,DummyEdge> registry; + + @Before + public void setUp() throws Exception { + registry = new ElementParserRegistry,DummyVertex,DummyEdge>( + new KeyMap(), + new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), + new DummyEdge.EdgeFactory(), + new DummyEdge.HyperEdgeFactory()); + } + + @After + public void tearDown() throws Exception { + registry = null; + } + + protected Object readObject(String xml) throws Exception { + + Reader fileReader = new StringReader(xml); + XMLInputFactory factory = XMLInputFactory.newInstance(); + XMLEventReader xmlEventReader = factory.createXMLEventReader(fileReader); + xmlEventReader = factory.createFilteredReader(xmlEventReader, + new GraphMLEventFilter()); + + try { + while( xmlEventReader.hasNext() ) { + XMLEvent event = xmlEventReader.nextEvent(); + if (event.isStartElement()) { + + StartElement start = event.asStartElement(); + String name = start.getName().getLocalPart(); + return registry.getParser(name).parse(xmlEventReader, start); + } + } + } finally { + xmlEventReader.close(); + } + + Assert.fail("failed to read object from XML: " + xml); + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEdgeElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEdgeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEdgeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEdgeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.EdgeMetadata; + +public class TestEdgeElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoSource() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test(expected= GraphIOException.class) + public void testNoTarget() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testId() throws Exception { + + String xml = + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals("e1", edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(null, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + } + + @Test + public void testDirectedTrue() throws Exception { + + String xml = + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(true, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + } + + @Test + public void testDirectedFalse() throws Exception { + + String xml = + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(false, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + } + + @Test + public void testSourceTargetPorts() throws Exception { + + String xml = + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(null, edge.isDirected()); + Assert.assertEquals("a", edge.getSourcePort()); + Assert.assertEquals("b", edge.getTargetPort()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "hello world" + + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals("hello world", edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(null, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + } + + @Test + public void testUserAttributes() throws Exception { + + String xml = + "" + + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(null, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + Assert.assertEquals(1, edge.getProperties().size()); + Assert.assertEquals("abc123", edge.getProperty("bob")); + } + + @Test + public void testData() throws Exception { + + String xml = + "" + + "value1" + + "value2" + + ""; + + EdgeMetadata edge = (EdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals("1", edge.getSource()); + Assert.assertEquals("2", edge.getTarget()); + Assert.assertEquals(null, edge.isDirected()); + Assert.assertEquals(null, edge.getSourcePort()); + Assert.assertEquals(null, edge.getTargetPort()); + Assert.assertEquals(2, edge.getProperties().size()); + Assert.assertEquals("value1", edge.getProperty("d1")); + Assert.assertEquals("value2", edge.getProperty("d2")); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEndpointElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEndpointElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEndpointElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestEndpointElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.EndpointMetadata; +import edu.uci.ics.jung.io.graphml.EndpointMetadata.EndpointType; + +public class TestEndpointElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoNode() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testId() throws Exception { + + String xml = + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals("ep1", ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.UNDIR, ep.getEndpointType()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "hello world" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals("ep1", ep.getId()); + Assert.assertEquals("hello world", ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.UNDIR, ep.getEndpointType()); + } + + @Test + public void testPort() throws Exception { + + String xml = + "" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals("ep1", ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals("abc123", ep.getPort()); + Assert.assertEquals(EndpointType.UNDIR, ep.getEndpointType()); + } + + @Test + public void testTypeIn() throws Exception { + + String xml = + "" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals(null, ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.IN, ep.getEndpointType()); + } + + @Test + public void testTypeOut() throws Exception { + + String xml = + "" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals(null, ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.OUT, ep.getEndpointType()); + } + + @Test + public void testTypeUndir() throws Exception { + + String xml = + "" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals(null, ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.UNDIR, ep.getEndpointType()); + } + + @Test + public void testTypeInvalid() throws Exception { + + String xml = + "" + + ""; + + EndpointMetadata ep = (EndpointMetadata) readObject(xml); + Assert.assertNotNull(ep); + Assert.assertEquals("1", ep.getNode()); + Assert.assertEquals(null, ep.getId()); + Assert.assertEquals(null, ep.getDescription()); + Assert.assertEquals(null, ep.getPort()); + Assert.assertEquals(EndpointType.UNDIR, ep.getEndpointType()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestGraphElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestGraphElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestGraphElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestGraphElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.EdgeMetadata; +import edu.uci.ics.jung.io.graphml.GraphMetadata; +import edu.uci.ics.jung.io.graphml.NodeMetadata; +import edu.uci.ics.jung.io.graphml.GraphMetadata.EdgeDefault; + +public class TestGraphElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoEdgeDefault() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testEdgeDefaultDirected() throws Exception { + + String xml = + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.DIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(0, g.getNodeMap().size()); + Assert.assertEquals(0, g.getEdgeMap().size()); + Assert.assertEquals(0, g.getHyperEdgeMap().size()); + } + + @Test + public void testEdgeDefaultUndirected() throws Exception { + + String xml = + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(0, g.getNodeMap().size()); + Assert.assertEquals(0, g.getEdgeMap().size()); + Assert.assertEquals(0, g.getHyperEdgeMap().size()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "hello world" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals("hello world", g.getDescription()); + Assert.assertEquals(0, g.getNodeMap().size()); + Assert.assertEquals(0, g.getEdgeMap().size()); + Assert.assertEquals(0, g.getHyperEdgeMap().size()); + } + + @Test + public void testNodes() throws Exception { + + String xml = + "" + + "" + + "" + + "" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(3, g.getNodeMap().size()); + List nodes = new ArrayList(g.getNodeMap().values()); + Collections.sort(nodes, new Comparator() { + public int compare(NodeMetadata o1, NodeMetadata o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + Assert.assertEquals("1", nodes.get(0).getId()); + Assert.assertEquals("2", nodes.get(1).getId()); + Assert.assertEquals("3", nodes.get(2).getId()); + } + + @Test + public void testEdges() throws Exception { + + String xml = + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + List edges = new ArrayList(g.getEdgeMap().values()); + Collections.sort(edges, new Comparator() { + public int compare(EdgeMetadata o1, EdgeMetadata o2) { + return o1.getSource().compareTo(o2.getSource()); + } + }); + Assert.assertEquals(2, edges.size()); + Assert.assertEquals("1", edges.get(0).getSource()); + Assert.assertEquals("2", edges.get(1).getSource()); + } + + @Test + public void testHyperEdges() throws Exception { + + String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(3, g.getHyperEdgeMap().size()); + } + + @Test + public void testUserAttributes() throws Exception { + + String xml = + "" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(1, g.getProperties().size()); + Assert.assertEquals("abc123", g.getProperty("bob")); + } + + @Test + public void testData() throws Exception { + + String xml = + "" + + "value1" + + "value2" + + ""; + + GraphMetadata g = (GraphMetadata) readObject(xml); + Assert.assertNotNull(g); + Assert.assertEquals(EdgeDefault.UNDIRECTED, g.getEdgeDefault()); + Assert.assertEquals(null, g.getId()); + Assert.assertEquals(null, g.getDescription()); + Assert.assertEquals(2, g.getProperties().size()); + Assert.assertEquals("value1", g.getProperty("d1")); + Assert.assertEquals("value2", g.getProperty("d2")); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestHyperEdgeElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestHyperEdgeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestHyperEdgeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestHyperEdgeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.graphml.HyperEdgeMetadata; + +public class TestHyperEdgeElementParser extends AbstractParserTest { + + @Test + public void testEmpty() throws Exception { + + String xml = + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals(0, edge.getEndpoints().size()); + } + + @Test + public void testId() throws Exception { + + String xml = + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals("e1", edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals(0, edge.getEndpoints().size()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "hello world" + + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals("hello world", edge.getDescription()); + Assert.assertEquals(0, edge.getEndpoints().size()); + } + + @Test + public void testEndpoints() throws Exception { + + String xml = + "" + + "" + + "" + + "" + + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals(3, edge.getEndpoints().size()); + Assert.assertEquals("1", edge.getEndpoints().get(0).getNode()); + Assert.assertEquals("2", edge.getEndpoints().get(1).getNode()); + Assert.assertEquals("3", edge.getEndpoints().get(2).getNode()); + } + + @Test + public void testUserAttributes() throws Exception { + + String xml = + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals(0, edge.getEndpoints().size()); + Assert.assertEquals(1, edge.getProperties().size()); + Assert.assertEquals("abc123", edge.getProperty("bob")); + } + + @Test + public void testData() throws Exception { + + String xml = + "" + + "value1" + + "value2" + + ""; + + HyperEdgeMetadata edge = (HyperEdgeMetadata) readObject(xml); + Assert.assertNotNull(edge); + Assert.assertEquals(null, edge.getId()); + Assert.assertEquals(null, edge.getDescription()); + Assert.assertEquals(0, edge.getEndpoints().size()); + Assert.assertEquals(2, edge.getProperties().size()); + Assert.assertEquals("value1", edge.getProperty("d1")); + Assert.assertEquals("value2", edge.getProperty("d2")); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestKeyElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestKeyElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestKeyElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestKeyElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.Key; + +public class TestKeyElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoId() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testId() throws Exception { + + String xml = + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.ALL, key.getForType()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "this is my key" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals("this is my key", key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.ALL, key.getForType()); + } + + @Test + public void testDefault() throws Exception { + + String xml = + "" + + "yellow" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals("yellow", key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.ALL, key.getForType()); + } + + @Test + public void testAttrNameType() throws Exception { + + String xml = + "" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals("myattr", key.getAttributeName()); + Assert.assertEquals("double", key.getAttributeType()); + Assert.assertEquals(Key.ForType.ALL, key.getForType()); + } + + @Test + public void testForNode() throws Exception { + + String xml = + "" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.NODE, key.getForType()); + } + + @Test + public void testForEdge() throws Exception { + + String xml = + "" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.EDGE, key.getForType()); + } + + @Test + public void testForGraph() throws Exception { + + String xml = + "" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.GRAPH, key.getForType()); + } + + @Test + public void testForAll() throws Exception { + + String xml = + "" + + ""; + + Key key = (Key) readObject(xml); + Assert.assertNotNull(key); + Assert.assertEquals("d1", key.getId()); + Assert.assertEquals(null, key.getDescription()); + Assert.assertEquals(null, key.getDefaultValue()); + Assert.assertEquals(null, key.getAttributeName()); + Assert.assertEquals(null, key.getAttributeType()); + Assert.assertEquals(Key.ForType.ALL, key.getForType()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestNodeElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestNodeElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestNodeElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestNodeElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.NodeMetadata; + +public class TestNodeElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoId() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testId() throws Exception { + + String xml = + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals(null, node.getDescription()); + Assert.assertEquals(0, node.getPorts().size()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "this is my node" + + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals("this is my node", node.getDescription()); + Assert.assertEquals(0, node.getPorts().size()); + } + + @Test + public void testPort() throws Exception { + + String xml = + "" + + "this is my node" + + "" + + "port 1" + + "" + + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals("this is my node", node.getDescription()); + Assert.assertEquals(1, node.getPorts().size()); + Assert.assertEquals("p1", node.getPorts().get(0).getName()); + } + + @Test + public void testMultiPort() throws Exception { + + String xml = + "" + + "this is my node" + + "" + + "" + + "" + + "" + + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals("this is my node", node.getDescription()); + Assert.assertEquals(4, node.getPorts().size()); + Assert.assertEquals("p1", node.getPorts().get(0).getName()); + Assert.assertEquals("p2", node.getPorts().get(1).getName()); + Assert.assertEquals("p3", node.getPorts().get(2).getName()); + Assert.assertEquals("p4", node.getPorts().get(3).getName()); + } + + @Test + public void testUserAttributes() throws Exception { + + String xml = + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals(1, node.getProperties().size()); + Assert.assertEquals("abc123", node.getProperty("bob")); + Assert.assertEquals(0, node.getPorts().size()); + } + + @Test + public void testData() throws Exception { + + String xml = + "" + + "value1" + + "value2" + + ""; + + NodeMetadata node = (NodeMetadata) readObject(xml); + Assert.assertNotNull(node); + Assert.assertEquals("1", node.getId()); + Assert.assertEquals(2, node.getProperties().size()); + Assert.assertEquals("value1", node.getProperty("d1")); + Assert.assertEquals("value2", node.getProperty("d2")); + Assert.assertEquals(0, node.getPorts().size()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestPortElementParser.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestPortElementParser.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestPortElementParser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/parser/TestPortElementParser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml.parser; + +import org.junit.Assert; +import org.junit.Test; + +import edu.uci.ics.jung.io.GraphIOException; +import edu.uci.ics.jung.io.graphml.PortMetadata; + +public class TestPortElementParser extends AbstractParserTest { + + @Test(expected= GraphIOException.class) + public void testNoName() throws Exception { + + String xml = + ""; + + readObject(xml); + } + + @Test + public void testName() throws Exception { + + String xml = + ""; + + PortMetadata port = (PortMetadata) readObject(xml); + Assert.assertNotNull(port); + Assert.assertEquals("p1", port.getName()); + Assert.assertEquals(null, port.getDescription()); + } + + @Test + public void testDesc() throws Exception { + + String xml = + "" + + "this is my port" + + ""; + + PortMetadata port = (PortMetadata) readObject(xml); + Assert.assertNotNull(port); + Assert.assertEquals("p1", port.getName()); + Assert.assertEquals("this is my port", port.getDescription()); + } + + @Test + public void testUserAttributes() throws Exception { + + String xml = + ""; + + PortMetadata port = (PortMetadata) readObject(xml); + Assert.assertNotNull(port); + Assert.assertEquals("p1", port.getName()); + Assert.assertEquals(1, port.getProperties().size()); + Assert.assertEquals("abc123", port.getProperty("bob")); + } + + @Test + public void testData() throws Exception { + + String xml = + "" + + "value1" + + "value2" + + ""; + + PortMetadata port = (PortMetadata) readObject(xml); + Assert.assertNotNull(port); + Assert.assertEquals("p1", port.getName()); + Assert.assertEquals(2, port.getProperties().size()); + Assert.assertEquals("value1", port.getProperty("d1")); + Assert.assertEquals("value2", port.getProperty("d2")); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/TestGraphMLReader2.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/TestGraphMLReader2.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/TestGraphMLReader2.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/graphml/TestGraphMLReader2.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ + +package edu.uci.ics.jung.io.graphml; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.SetHypergraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.io.GraphIOException; + +public class TestGraphMLReader2 { + static final String graphMLDocStart = "" + + ""; + + private GraphMLReader2, DummyVertex, DummyEdge> reader; + + @After + public void tearDown() throws Exception { + if (reader != null) { + reader.close(); + } + reader = null; + } + + + @Test(expected = GraphIOException.class) + public void testEmptyFile() throws Exception { + + String xml = ""; + readGraph(xml, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + } + + @Test + public void testBasics() throws Exception { + + String xml = graphMLDocStart + + "" + + "yellow" + + "" + + "" + + "" + + "" + "green" + + "" + "" + "" + + "blue" + "" + + "" + + "1.0" + "" + "" + ""; + + // Read the graph object. + Hypergraph graph = readGraph(xml, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + + // Check out the graph. + Assert.assertNotNull(graph); + Assert.assertEquals(3, graph.getVertexCount()); + Assert.assertEquals(1, graph.getEdgeCount()); + Assert.assertEquals(0, graph.getEdgeCount(EdgeType.DIRECTED)); + Assert.assertEquals(1, graph.getEdgeCount(EdgeType.UNDIRECTED)); + + // Check out metadata. + Assert.assertEquals(1, reader.getGraphMLDocument().getGraphMetadata().size()); + List edges = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getEdgeMap().values()); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals("n0", edges.get(0).getSource()); + Assert.assertEquals("n2", edges.get(0).getTarget()); + } + + @Test + public void testData() throws Exception { + + String xml = + graphMLDocStart + + "" + + "yellow" + + "" + + "" + + "" + + "" + + "green" + + "" + + "" + + "" + + "blue" + + "" + + "" + + "1.0" + + "" + + "" + + ""; + + // Read the graph object. + readGraph(xml, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + + // Check out metadata. + Assert.assertEquals(1, reader.getGraphMLDocument().getGraphMetadata().size()); + List edges = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getEdgeMap().values()); + List nodes = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getNodeMap().values()); + Collections.sort(nodes, new Comparator() { + public int compare(NodeMetadata o1, NodeMetadata o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals("1.0", edges.get(0).getProperties().get("d1")); + Assert.assertEquals(3, nodes.size()); + Assert.assertEquals("green", nodes.get(0).getProperties().get("d0")); + Assert.assertEquals("yellow", nodes.get(1).getProperties().get("d0")); + Assert.assertEquals("blue", nodes.get(2).getProperties().get("d0")); + } + + @Test(expected = GraphIOException.class) + public void testEdgeWithInvalidNode() throws Exception { + + String xml = graphMLDocStart + + "" + + "yellow" + + "" + + "" + + "" + + "" + "green" + + "" + "" + "" + + "blue" + "" + + "" + // Invalid + // node: n3 + "1.0" + "" + ""; + + readGraph(xml, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), new DummyVertex.Factory(), + new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + } + + @Test + public void testHypergraph() throws Exception { + + String xml = graphMLDocStart + + "" + + "yellow" + + "" + + "" + + "" + + "" + "green" + + "" + "" + "" + + "blue" + "" + + "" + + "" + "" + + "" + "" + "" + ""; + + // Read the graph object. + Hypergraph graph = readGraph(xml, new DummyGraphObjectBase.SetHypergraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + + // Check out the graph. + Assert.assertNotNull(graph); + Assert.assertEquals(3, graph.getVertexCount()); + Assert.assertEquals(1, graph.getEdgeCount()); + Assert.assertEquals(0, graph.getEdgeCount(EdgeType.DIRECTED)); + Assert.assertEquals(1, graph.getEdgeCount(EdgeType.UNDIRECTED)); + + // Check out metadata. + Assert.assertEquals(1, reader.getGraphMLDocument().getGraphMetadata().size()); + List edges = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getHyperEdgeMap().values()); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(3, edges.get(0).getEndpoints().size()); + Assert.assertEquals("n0", edges.get(0).getEndpoints().get(0).getNode()); + Assert.assertEquals("n1", edges.get(0).getEndpoints().get(1).getNode()); + Assert.assertEquals("n2", edges.get(0).getEndpoints().get(2).getNode()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidGraphFactory() throws Exception { + + // Need a hypergraph + String xml = graphMLDocStart + + "" + + "yellow" + + "" + + "" + + "" + + "" + "green" + + "" + "" + "" + + "blue" + "" + + "" + + "" + "" + + "" + "" + ""; + + // This will attempt to add an edge with an invalid number of incident vertices (3) + // for an UndirectedGraph, which should trigger an IllegalArgumentException. + readGraph(xml, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + } + + @Test + public void testAttributesFile() throws Exception { + + // Read the graph object. + Hypergraph graph = readGraphFromFile("attributes.graphml", new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + + Assert.assertEquals(6, graph.getVertexCount()); + Assert.assertEquals(7, graph.getEdgeCount()); + + Assert.assertEquals(1, reader.getGraphMLDocument().getGraphMetadata().size()); + + // Test node ids + int id = 0; + List nodes = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getNodeMap().values()); + Collections.sort(nodes, new Comparator() { + public int compare(NodeMetadata o1, NodeMetadata o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + Assert.assertEquals(6, nodes.size()); + for (NodeMetadata md : nodes) { + Assert.assertEquals('n', md.getId().charAt(0)); + Assert.assertEquals(id++, Integer.parseInt(md.getId().substring(1))); + } + + // Test edge ids + id = 0; + List edges = new ArrayList(reader.getGraphMLDocument().getGraphMetadata().get(0).getEdgeMap().values()); + Collections.sort(edges, new Comparator() { + public int compare(EdgeMetadata o1, EdgeMetadata o2) { + return o1.getId().compareTo(o2.getId()); + } + }); + Assert.assertEquals(7, edges.size()); + for (EdgeMetadata md : edges) { + Assert.assertEquals('e', md.getId().charAt(0)); + Assert.assertEquals(id++, Integer.parseInt(md.getId().substring(1))); + } + + Assert.assertEquals("green", nodes.get(0).getProperties().get("d0")); + Assert.assertEquals("yellow", nodes.get(1).getProperties().get("d0")); + Assert.assertEquals("blue", nodes.get(2).getProperties().get("d0")); + Assert.assertEquals("red", nodes.get(3).getProperties().get("d0")); + Assert.assertEquals("yellow", nodes.get(4).getProperties().get("d0")); + Assert.assertEquals("turquoise", nodes.get(5).getProperties().get("d0")); + + Assert.assertEquals("1.0", edges.get(0).getProperties().get("d1")); + Assert.assertEquals("1.0", edges.get(1).getProperties().get("d1")); + Assert.assertEquals("2.0", edges.get(2).getProperties().get("d1")); + Assert.assertEquals(null, edges.get(3).getProperties().get("d1")); + Assert.assertEquals(null, edges.get(4).getProperties().get("d1")); + Assert.assertEquals(null, edges.get(5).getProperties().get("d1")); + Assert.assertEquals("1.1", edges.get(6).getProperties().get("d1")); + } + + @Test + public void testHypergraphFile() throws Exception { + + Function> graphFactory = new Function>() { + public Hypergraph apply(GraphMetadata md) { + return new SetHypergraph(); + } + }; + + Function vertexFactory = new Function() { + int n = 0; + + public Number apply(NodeMetadata md) { + return n++; + } + }; + + Function edgeFactory = new Function() { + int n = 100; + + public Number apply(EdgeMetadata md) { + return n++; + } + }; + + Function hyperEdgeFactory = new Function() { + int n = 0; + + public Number apply(HyperEdgeMetadata md) { + return n++; + } + }; + + // Read the graph object. + Reader fileReader = new InputStreamReader(getClass().getResourceAsStream("hyper.graphml")); + GraphMLReader2, Number, Number> hyperreader = + new GraphMLReader2, Number, Number>(fileReader, + graphFactory, vertexFactory, edgeFactory, hyperEdgeFactory); + + // Read the graph. + Hypergraph graph = hyperreader.readGraph(); + + Assert.assertEquals(graph.getVertexCount(), 7); + Assert.assertEquals(graph.getEdgeCount(), 4); + + // n0 + Set incident = new HashSet(); + incident.add(0); + incident.add(100); + Assert.assertEquals(incident, graph.getIncidentEdges(0)); + + // n1 + incident.clear(); + incident.add(0); + incident.add(2); + Assert.assertEquals(incident, graph.getIncidentEdges(1)); + + // n2 + incident.clear(); + incident.add(0); + Assert.assertEquals(incident, graph.getIncidentEdges(2)); + + // n3 + incident.clear(); + incident.add(1); + incident.add(2); + Assert.assertEquals(incident, graph.getIncidentEdges(3)); + + // n4 + incident.clear(); + incident.add(1); + incident.add(100); + Assert.assertEquals(incident, graph.getIncidentEdges(4)); + + // n5 + incident.clear(); + incident.add(1); + Assert.assertEquals(incident, graph.getIncidentEdges(5)); + + // n6 + incident.clear(); + incident.add(1); + Assert.assertEquals(incident, graph.getIncidentEdges(6)); + } + + /*@Test + public void testReader1Perf() throws Exception { + String fileName = "attributes.graphml"; + + long totalTime = 0; + int numTrials = 1000; + + for( int ix=0; ix, DummyVertex, DummyEdge> reader = new GraphMLReader, DummyVertex, DummyEdge>(new Factory() { + + public DummyVertex create() { + return new DummyVertex(); + } + + }, new Factory() { + public DummyEdge create() { + return new DummyEdge(); + } + }); + + Thread.sleep(10); + + long start = System.currentTimeMillis(); + Hypergraph graph = new UndirectedSparseGraph(); + reader.load(fileReader, graph); + long duration = System.currentTimeMillis() - start; + totalTime += duration; + } + + double avgTime = ((double)totalTime / (double)numTrials) / 1000.0; + + System.out.printf("Reader1: totalTime=%6d, numTrials=%6d, avgTime=%2.6f seconds", totalTime, numTrials, avgTime); + System.out.println(); + } + + @Test + public void testReader2Perf() throws Exception { + String fileName = "attributes.graphml"; + + long totalTime = 0; + int numTrials = 1000; + + // Test reader2 + for( int ix=0; ix, DummyVertex, DummyEdge>( + fileReader, new DummyGraphObjectBase.UndirectedSparseGraphFactory(), + new DummyVertex.Factory(), new DummyEdge.EdgeFactory(), new DummyEdge.HyperEdgeFactory()); + reader.init(); + + Thread.sleep(10); + + long start = System.currentTimeMillis(); + reader.readGraph(); + long duration = System.currentTimeMillis() - start; + totalTime += duration; + + reader.close(); + } + + double avgTime = ((double)totalTime / (double)numTrials) / 1000.0; + + System.out.printf("Reader2: totalTime=%6d, numTrials=%6d, avgTime=%2.6f seconds", totalTime, numTrials, avgTime); + System.out.println(); + }*/ + + private Hypergraph readGraph(String xml, Function> gf, + DummyVertex.Factory nf, DummyEdge.EdgeFactory ef, DummyEdge.HyperEdgeFactory hef) + throws GraphIOException { + Reader fileReader = new StringReader(xml); + reader = new GraphMLReader2, DummyVertex, DummyEdge>( + fileReader, gf, nf, ef, hef); + + return reader.readGraph(); + } + + private Hypergraph readGraphFromFile(String file, Function> gf, + DummyVertex.Factory nf, DummyEdge.EdgeFactory ef, DummyEdge.HyperEdgeFactory hef) + throws Exception { + InputStream is = getClass().getResourceAsStream(file); + Reader fileReader = new InputStreamReader(is); + reader = new GraphMLReader2, DummyVertex, DummyEdge>( + fileReader, gf, nf, ef, hef); + + return reader.readGraph(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/PajekNetIOTest.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/PajekNetIOTest.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/PajekNetIOTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/PajekNetIOTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,433 @@ +/* + * Created on May 3, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.awt.geom.Point2D; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.UndirectedSparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + + +/** + * Needed tests: + * - edgeslist, arcslist + * - unit test to catch bug in readArcsOrEdges() [was skipping until e_pred, not c_pred] + * + * @author Joshua O'Madadhain + * @author Tom Nelson - converted to jung2 + */ +public class PajekNetIOTest extends TestCase +{ + protected String[] vertex_labels = {"alpha", "beta", "gamma", "delta", "epsilon"}; + + Supplier> directedGraphFactory; + Supplier> undirectedGraphFactory; + Supplier> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + PajekNetReader, Number,Number> pnr; + + @Override + protected void setUp() { + directedGraphFactory = new Supplier>() { + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + undirectedGraphFactory = new Supplier>() { + public UndirectedGraph get() { + return new UndirectedSparseMultigraph(); + } + }; + graphFactory = new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + vertexFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + edgeFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + pnr = new PajekNetReader, Number,Number>(vertexFactory, edgeFactory); + + } + + public void testNull() + { + + } + + + public void testFileNotFound() + { + try + { + pnr.load("/dev/null/foo", graphFactory); + fail("File load did not fail on nonexistent file"); + } + catch (FileNotFoundException fnfe) + { + } + catch (IOException ioe) + { + fail("unexpected IOException"); + } + } + + public void testNoLabels() throws IOException + { + String test = "*Vertices 3\n1\n2\n3\n*Edges\n1 2\n2 2"; + Reader r = new StringReader(test); + + Graph g = pnr.load(r, undirectedGraphFactory); + assertEquals(g.getVertexCount(), 3); + assertEquals(g.getEdgeCount(), 2); + } + + public void testDirectedSaveLoadSave() throws IOException + { + Graph graph1 = directedGraphFactory.get(); + for(int i=0; i<5; i++) { + graph1.addVertex(i); + } +// GraphUtils.addVertices(graph1, 5); + List id = new ArrayList(graph1.getVertices());//Indexer.getIndexer(graph1); + GreekLabels gl = new GreekLabels(id); + int j=0; + graph1.addEdge(j++, 0, 1); + graph1.addEdge(j++, 0, 2); + graph1.addEdge(j++, 1, 2); + graph1.addEdge(j++, 1, 3); + graph1.addEdge(j++, 1, 4); + graph1.addEdge(j++, 4, 3); + + +// System.err.println("graph1 = "+graph1); +// for(Number edge : graph1.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge)); +// } +// for(Number v : graph1.getVertices()) { +// System.err.println(v+" outedges are "+graph1.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph1.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v)); +// } + + assertEquals(graph1.getEdgeCount(), 6); + + String testFilename = "dtest.net"; + String testFilename2 = testFilename + "2"; + + PajekNetWriter pnw = new PajekNetWriter(); + pnw.save(graph1, testFilename, gl, null, null); + + Graph graph2 = pnr.load(testFilename, directedGraphFactory); + +// System.err.println("graph2 = "+graph2); +// for(Number edge : graph2.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph2.getEdgeType(edge)); +// } +// for(Number v : graph2.getVertices()) { +// System.err.println(v+" outedges are "+graph2.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph2.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph2.getIncidentEdges(v)); +// } + + assertEquals(graph1.getVertexCount(), graph2.getVertexCount()); + assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount()); + + pnw.save(graph2, testFilename2, pnr.getVertexLabeller(), null, null); + + compareIndexedGraphs(graph1, graph2); + + Graph graph3 = pnr.load(testFilename2, graphFactory); + +// System.err.println("graph3 = "+graph3); +// for(Number edge : graph3.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph3.getEdgeType(edge)); +// } +// for(Number v : graph3.getVertices()) { +// System.err.println(v+" outedges are "+graph3.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph3.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph3.getIncidentEdges(v)); +// } + + compareIndexedGraphs(graph2, graph3); + + File file1 = new File(testFilename); + File file2 = new File(testFilename2); + + Assert.assertTrue(file1.length() == file2.length()); + file1.delete(); + file2.delete(); + } + + public void testUndirectedSaveLoadSave() throws IOException + { + UndirectedGraph graph1 = + undirectedGraphFactory.get(); + for(int i=0; i<5; i++) { + graph1.addVertex(i); + } + + List id = new ArrayList(graph1.getVertices()); + int j=0; + GreekLabels gl = new GreekLabels(id); + graph1.addEdge(j++, 0, 1); + graph1.addEdge(j++, 0, 2); + graph1.addEdge(j++, 1, 2); + graph1.addEdge(j++, 1, 3); + graph1.addEdge(j++, 1, 4); + graph1.addEdge(j++, 4, 3); + + assertEquals(graph1.getEdgeCount(), 6); + +// System.err.println("graph1 = "+graph1); +// for(Number edge : graph1.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge)); +// } +// for(Number v : graph1.getVertices()) { +// System.err.println(v+" outedges are "+graph1.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph1.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v)); +// } + + String testFilename = "utest.net"; + String testFilename2 = testFilename + "2"; + + PajekNetWriter pnw = new PajekNetWriter(); + pnw.save(graph1, testFilename, gl, null, null); + + Graph graph2 = pnr.load(testFilename, undirectedGraphFactory); + + +// System.err.println("graph2 = "+graph2); +// for(Number edge : graph2.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph2.getEdgeType(edge)); +// } +// for(Number v : graph2.getVertices()) { +// System.err.println(v+" outedges are "+graph2.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph2.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph2.getIncidentEdges(v)); +// } + + + assertEquals(graph1.getVertexCount(), graph2.getVertexCount()); + assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount()); + + pnw.save(graph2, testFilename2, pnr.getVertexLabeller(), null, null); + compareIndexedGraphs(graph1, graph2); + + Graph graph3 = pnr.load(testFilename2, graphFactory); +// System.err.println("graph3 = "+graph3); +// for(Number edge : graph3.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph3.getEdgeType(edge)); +// } +// for(Number v : graph3.getVertices()) { +// System.err.println(v+" outedges are "+graph3.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph3.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph3.getIncidentEdges(v)); +// } + + compareIndexedGraphs(graph2, graph3); + + File file1 = new File(testFilename); + File file2 = new File(testFilename2); + + Assert.assertTrue(file1.length() == file2.length()); + file1.delete(); + file2.delete(); + } + + public void testMixedSaveLoadSave() throws IOException + { + Graph graph1 = new SparseMultigraph(); + for(int i=0; i<5; i++) { + graph1.addVertex(i); + } + int j=0; + + List id = new ArrayList(graph1.getVertices()); + GreekLabels gl = new GreekLabels(id); + Number[] edges = { 0,1,2,3,4,5 }; + + graph1.addEdge(j++, 0, 1, EdgeType.DIRECTED); + graph1.addEdge(j++, 0, 2, EdgeType.DIRECTED); + graph1.addEdge(j++, 1, 2, EdgeType.DIRECTED); + graph1.addEdge(j++, 1, 3); + graph1.addEdge(j++, 1, 4); + graph1.addEdge(j++, 4, 3); + + Map nr = new HashMap(); + for (int i = 0; i < edges.length; i++) + { + nr.put(edges[i], new Float(Math.random())); + } + + assertEquals(graph1.getEdgeCount(), 6); + +// System.err.println(" mixed graph1 = "+graph1); +// for(Number edge : graph1.getEdges()) { +// System.err.println("edge "+edge+" is directed? "+graph1.getEdgeType(edge)); +// } +// for(Number v : graph1.getVertices()) { +// System.err.println(v+" outedges are "+graph1.getOutEdges(v)); +// System.err.println(v+" inedges are "+graph1.getInEdges(v)); +// System.err.println(v+" incidentedges are "+graph1.getIncidentEdges(v)); +// } + + String testFilename = "mtest.net"; + String testFilename2 = testFilename + "2"; + + // assign arbitrary locations to each vertex + Map locations = new HashMap(); + for (Number v : graph1.getVertices()) { + locations.put(v, new Point2D.Double(v.intValue() * v.intValue(), 1 << v.intValue())); + } + Function vld = Functions.forMap(locations); + + PajekNetWriter pnw = new PajekNetWriter(); + pnw.save(graph1, testFilename, gl, Functions.forMap(nr), vld); + + Graph graph2 = pnr.load(testFilename, graphFactory); + Function pl = pnr.getVertexLabeller(); + List id2 = new ArrayList(graph2.getVertices()); + Function vld2 = pnr.getVertexLocationTransformer(); + + assertEquals(graph1.getVertexCount(), graph2.getVertexCount()); + assertEquals(graph1.getEdgeCount(), graph2.getEdgeCount()); + + // test vertex labels and locations + for (int i = 0; i < graph1.getVertexCount(); i++) + { + Number v1 = id.get(i); + Number v2 = id2.get(i); + assertEquals(gl.apply(v1), pl.apply(v2)); + assertEquals(vld.apply(v1), vld2.apply(v2)); + } + + // test edge weights + Function nr2 = pnr.getEdgeWeightTransformer(); + for (Number e2 : graph2.getEdges()) + { + Pair endpoints = graph2.getEndpoints(e2); + Number v1_2 = endpoints.getFirst(); + Number v2_2 = endpoints.getSecond(); + Number v1_1 = id.get(id2.indexOf(v1_2)); + Number v2_1 = id.get(id2.indexOf(v2_2)); + Number e1 = graph1.findEdge(v1_1, v2_1); + assertNotNull(e1); + assertEquals(nr.get(e1).floatValue(), nr2.apply(e2).floatValue(), 0.0001); + } + + pnw.save(graph2, testFilename2, pl, nr2, vld2); + + compareIndexedGraphs(graph1, graph2); + + pnr.setVertexLabeller(null); + Graph graph3 = pnr.load(testFilename2, graphFactory); + + compareIndexedGraphs(graph2, graph3); + + File file1 = new File(testFilename); + File file2 = new File(testFilename2); + + Assert.assertTrue(file1.length() == file2.length()); + file1.delete(); + file2.delete(); + + } + + + /** + * Tests to see whether these two graphs are structurally equivalent, based + * on the connectivity of the vertices with matching indices in each graph. + * Assumes a 0-based index. + * + * @param g1 + * @param g2 + */ + private void compareIndexedGraphs(Graph g1, Graph g2) + { + int n1 = g1.getVertexCount(); + int n2 = g2.getVertexCount(); + + assertEquals(n1, n2); + + assertEquals(g1.getEdgeCount(), g2.getEdgeCount()); + + List id1 = new ArrayList(g1.getVertices()); + List id2 = new ArrayList(g2.getVertices()); + + for (int i = 0; i < n1; i++) + { + Number v1 = id1.get(i); + Number v2 = id2.get(i); + assertNotNull(v1); + assertNotNull(v2); + + checkSets(g1.getPredecessors(v1), g2.getPredecessors(v2), id1, id2); + checkSets(g1.getSuccessors(v1), g2.getSuccessors(v2), id1, id2); + } + } + + private void checkSets(Collection s1, Collection s2, List id1, List id2) + { + for (Number u : s1) + { + int j = id1.indexOf(u); + assertTrue(s2.contains(id2.get(j))); + } + } + + private class GreekLabels implements Function + { + private List id; + + public GreekLabels(List id) + { + this.id = id; + } + + public String apply(V v) + { + return vertex_labels[id.indexOf(v)]; + } + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLReader.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLReader.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLReader.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLReader.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,280 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.io; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.xml.sax.SAXException; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.BiMap; + +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Hypergraph; +import edu.uci.ics.jung.graph.SetHypergraph; +import edu.uci.ics.jung.graph.UndirectedSparseGraph; + +/** + * @author Scott White + * @author Tom Nelson - converted to jung2 + */ +public class TestGraphMLReader extends TestCase +{ + + Supplier> graphFactory; + Supplier vertexFactory; + Supplier edgeFactory; + GraphMLReader, Number, Number> gmlreader; + + public static Test suite() + { + return new TestSuite(TestGraphMLReader.class); + } + + @Override + protected void setUp() throws ParserConfigurationException, SAXException + { + graphFactory = new Supplier>() + { + public Graph get() + { + return new DirectedSparseMultigraph(); + } + }; + vertexFactory = new Supplier() + { + int n = 0; + + public Number get() + { + return n++; + } + }; + edgeFactory = new Supplier() + { + int n = 0; + + public Number get() + { + return n++; + } + }; + gmlreader = new GraphMLReader, Number, Number>( + vertexFactory, edgeFactory); + } + + public void testLoad() throws IOException + { + String testFilename = "toy_graph.ml"; + + Graph graph = loadGraph(testFilename); + + Assert.assertEquals(graph.getVertexCount(), 3); + Assert.assertEquals(graph.getEdgeCount(), 3); + + BiMap vertex_ids = gmlreader.getVertexIDs(); + + Number joe = vertex_ids.inverse().get("1"); + Number bob = vertex_ids.inverse().get("2"); + Number sue = vertex_ids.inverse().get("3"); + + Assert.assertNotNull(joe); + Assert.assertNotNull(bob); + Assert.assertNotNull(sue); + + Map> vertex_metadata = + gmlreader.getVertexMetadata(); + Function name = + vertex_metadata.get("name").transformer; + Assert.assertEquals(name.apply(joe), "Joe"); + Assert.assertEquals(name.apply(bob), "Bob"); + Assert.assertEquals(name.apply(sue), "Sue"); + + Assert.assertTrue(graph.isPredecessor(joe, bob)); + Assert.assertTrue(graph.isPredecessor(bob, joe)); + Assert.assertTrue(graph.isPredecessor(sue, joe)); + Assert.assertFalse(graph.isPredecessor(joe, sue)); + Assert.assertFalse(graph.isPredecessor(sue, bob)); + Assert.assertFalse(graph.isPredecessor(bob, sue)); + + File testFile = new File(testFilename); + testFile.delete(); + } + + public void testAttributes() throws IOException + { + Graph graph = new UndirectedSparseGraph(); + gmlreader.load("src/test/resources/edu/uci/ics/jung/io/graphml/attributes.graphml", graph); + + Assert.assertEquals(graph.getVertexCount(), 6); + Assert.assertEquals(graph.getEdgeCount(), 7); + + // test vertex IDs + BiMap vertex_ids = gmlreader.getVertexIDs(); + for (Map.Entry entry : vertex_ids.entrySet()) + { + Assert.assertEquals(entry.getValue().charAt(0), 'n'); + Assert.assertEquals( + Integer.parseInt(entry.getValue().substring(1)), entry + .getKey().intValue()); + } + + // test edge IDs + BiMap edge_ids = gmlreader.getEdgeIDs(); + for (Map.Entry entry : edge_ids.entrySet()) + { + Assert.assertEquals(entry.getValue().charAt(0), 'e'); + Assert.assertEquals( + Integer.parseInt(entry.getValue().substring(1)), entry + .getKey().intValue()); + } + + // test data +// Map> vertex_data = gmlreader +// .getVertexData(); +// Map> edge_data = gmlreader +// .getEdgeData(); + Map> vertex_metadata = + gmlreader.getVertexMetadata(); + Map> edge_metadata = + gmlreader.getEdgeMetadata(); + + + // test vertex colors +// Transformer vertex_color = vertex_data.get("d0"); + Function vertex_color = + vertex_metadata.get("d0").transformer; + Assert.assertEquals(vertex_color.apply(0), "green"); + Assert.assertEquals(vertex_color.apply(1), "yellow"); + Assert.assertEquals(vertex_color.apply(2), "blue"); + Assert.assertEquals(vertex_color.apply(3), "red"); + Assert.assertEquals(vertex_color.apply(4), "yellow"); + Assert.assertEquals(vertex_color.apply(5), "turquoise"); + + // test edge weights +// Transformer edge_weight = edge_data.get("d1"); + Function edge_weight = + edge_metadata.get("d1").transformer; + Assert.assertEquals(edge_weight.apply(0), "1.0"); + Assert.assertEquals(edge_weight.apply(1), "1.0"); + Assert.assertEquals(edge_weight.apply(2), "2.0"); + Assert.assertEquals(edge_weight.apply(3), null); + Assert.assertEquals(edge_weight.apply(4), null); + Assert.assertEquals(edge_weight.apply(5), null); + Assert.assertEquals(edge_weight.apply(6), "1.1"); + + } + + public void testLoadHypergraph() throws IOException, + ParserConfigurationException, SAXException + { + Hypergraph graph = new SetHypergraph(); + GraphMLReader, Number, Number> hyperreader = + new GraphMLReader, Number, Number>( + vertexFactory, edgeFactory); + hyperreader.load("src/test/resources/edu/uci/ics/jung/io/graphml/hyper.graphml", graph); + + Assert.assertEquals(graph.getVertexCount(), 7); + Assert.assertEquals(graph.getEdgeCount(), 4); + + // n0 + Set incident = new HashSet(); + incident.add(0); + incident.add(3); + Assert.assertEquals(graph.getIncidentEdges(0), incident); + + // n1 + incident.clear(); + incident.add(0); + incident.add(2); + Assert.assertEquals(graph.getIncidentEdges(1), incident); + + // n2 + incident.clear(); + incident.add(0); + Assert.assertEquals(graph.getIncidentEdges(2), incident); + + // n3 + incident.clear(); + incident.add(1); + incident.add(2); + Assert.assertEquals(graph.getIncidentEdges(3), incident); + + // n4 + incident.clear(); + incident.add(1); + incident.add(3); + Assert.assertEquals(graph.getIncidentEdges(4), incident); + + // n5 + incident.clear(); + incident.add(1); + Assert.assertEquals(graph.getIncidentEdges(5), incident); + + // n6 + incident.clear(); + incident.add(1); + Assert.assertEquals(graph.getIncidentEdges(6), incident); + } + + private Graph loadGraph(String testFilename) + throws IOException + { + BufferedWriter writer = new BufferedWriter(new FileWriter( + testFilename)); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.write("\n"); + writer.close(); + + Graph graph = graphFactory.get(); + gmlreader.load(testFilename, graph); + return graph; + } + +// public void testSave() { +// String testFilename = "toy_graph.ml"; +// Graph oldGraph = loadGraph(testFilename); +//// GraphMLFile graphmlFile = new GraphMLFile(); +// String newFilename = testFilename + "_save"; +// gmlreader.save(oldGraph,newFilename); +// Graph newGraph = gmlreader.load(newFilename); +// Assert.assertEquals(oldGraph.getVertexCount(),newGraph.getVertexCount()); +// Assert.assertEquals(oldGraph.getEdgeCount(),newGraph.getEdgeCount()); +// File testFile = new File(testFilename); +// testFile.delete(); +// File newFile = new File(newFilename); +// newFile.delete(); +// +// +// } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLWriter.java libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLWriter.java --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLWriter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/java/edu/uci/ics/jung/io/TestGraphMLWriter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,169 @@ +/* + * Created on Jun 22, 2008 + * + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.io; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.xml.sax.SAXException; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.TestGraphs; + +public class TestGraphMLWriter extends TestCase +{ + public void testBasicWrite() throws IOException, ParserConfigurationException, SAXException + { + Graph g = TestGraphs.createTestGraph(true); + GraphMLWriter gmlw = new GraphMLWriter(); + Function edge_weight = new Function() + { + public String apply(Number n) + { + return String.valueOf(n.intValue()); + } + }; + + Function vertex_name = Functions.identity(); + //TransformerUtils.nopTransformer(); + + gmlw.addEdgeData("weight", "integer value for the edge", + Integer.toString(-1), edge_weight); + gmlw.addVertexData("name", "identifier for the vertex", null, vertex_name); + gmlw.setEdgeIDs(edge_weight); + gmlw.setVertexIDs(vertex_name); + gmlw.save(g, new FileWriter("src/test/resources/testbasicwrite.graphml")); + + // TODO: now read it back in and compare the graph connectivity + // and other metadata with what's in TestGraphs.pairs[], etc. +// Factory vertex_factory = null; +// Factory edge_factory = FactoryUtils.instantiateFactory(Object.class); +// GraphMLReader, String, Object> gmlr = +// new GraphMLReader, String, Object>( +// vertex_factory, edge_factory); + GraphMLReader, String, Object> gmlr = + new GraphMLReader, String, Object>(); + Graph g2 = new DirectedSparseGraph(); + gmlr.load("src/test/resources/testbasicwrite.graphml", g2); + Map> edge_metadata = + gmlr.getEdgeMetadata(); + Function edge_weight2 = + edge_metadata.get("weight").transformer; + validateTopology(g, g2, edge_weight, edge_weight2); + + // TODO: delete graph file when done + File f = new File("src/test/resources/testbasicwrite.graphml"); + f.delete(); + } + + public void testMixedGraph() throws IOException, ParserConfigurationException, SAXException + { + Graph g = TestGraphs.getSmallGraph(); + GraphMLWriter gmlw = new GraphMLWriter(); + Function edge_weight = new Function() + { + public String apply(Number n) + { + return String.valueOf(n.doubleValue()); + } + }; + + gmlw.addEdgeData("weight", "integer value for the edge", + Integer.toString(-1), edge_weight); + gmlw.setEdgeIDs(edge_weight); + gmlw.save(g, new FileWriter("src/test/resources/testmixedgraph.graphml")); + + // TODO: now read it back in and compare the graph connectivity + // and other metadata with what's in TestGraphs, etc. + GraphMLReader,String,Object> gmlr = + new GraphMLReader,String,Object>(); + Graph g2 = new SparseMultigraph(); + gmlr.load("src/test/resources/testmixedgraph.graphml", g2); + Map> edge_metadata = + gmlr.getEdgeMetadata(); + Function edge_weight2 = + edge_metadata.get("weight").transformer; + validateTopology(g, g2, edge_weight, edge_weight2); + + // TODO: delete graph file when done + File f = new File("src/test/resources/testmixedgraph.graphml"); + f.delete(); + } + + public > void validateTopology(Graph g, Graph g2, + Function edge_weight, Function edge_weight2) + { + Assert.assertEquals(g2.getEdgeCount(), g.getEdgeCount()); + List g_vertices = new ArrayList(g.getVertices()); + List g2_vertices = new ArrayList(g2.getVertices()); + Collections.sort(g_vertices); + Collections.sort(g2_vertices); + Assert.assertEquals(g_vertices, g2_vertices); + + Set g_edges = new HashSet(); + for (Number n : g.getEdges()) + g_edges.add(String.valueOf(n)); + Set g2_edges = new HashSet(g2.getEdges()); + Assert.assertEquals(g_edges, g2_edges); + + for (T v : g2.getVertices()) + { + for (T w : g2.getVertices()) + { + Assert.assertEquals(g.isNeighbor(v, w), + g2.isNeighbor(v, w)); + Set e = new HashSet(); + for (Number n : g.findEdgeSet(v, w)) + e.add(String.valueOf(n)); + Set e2 = new HashSet(g2.findEdgeSet(v, w)); + Assert.assertEquals(e.size(), e2.size()); + Assert.assertEquals(e, e2); + } + } + + for (Object o : g2.getEdges()) + { + String weight = edge_weight.apply(new Double((String)o)); + String weight2 = edge_weight2.apply(o); + Assert.assertEquals(weight2, weight); + } +// Number n = g.findEdge(v, w); +// Object o = g2.findEdge(v, w); +// if (n != null) +// { +// String weight = edge_weight.apply(n); +// String weight2 = edge_weight2.apply(o); +// Assert.assertEquals(weight2, weight); +// } +// } +// } + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/attributes.graphml libjung-free-java-2.1.1/jung-io/src/test/resources/attributes.graphml --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/attributes.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/resources/attributes.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,41 @@ + + + + yellow + + + + + green + + + + blue + + + red + + + + turquoise + + + 1.0 + + + 1.0 + + + 2.0 + + + + + + 1.1 + + + \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/attributes.graphml libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/attributes.graphml --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/attributes.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/attributes.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,41 @@ + + + + yellow + + + + + green + + + + blue + + + red + + + + turquoise + + + 1.0 + + + 1.0 + + + 2.0 + + + + + + 1.1 + + + \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/hyper.graphml libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/hyper.graphml --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/hyper.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/hyper.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/multigraph.graphml libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/multigraph.graphml --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/multigraph.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/resources/edu/uci/ics/jung/io/graphml/multigraph.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,66 @@ + + + + yellow + + + + + green + + + + blue + + + red + + + + turquoise + + + 1.0 + + + 1.0 + + + 2.0 + + + + + + 1.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/hyper.graphml libjung-free-java-2.1.1/jung-io/src/test/resources/hyper.graphml --- libjung-free-java-2.0.1+dfsg/jung-io/src/test/resources/hyper.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-io/src/test/resources/hyper.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-io-2.0.1-sources.jar and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-io-2.0.1-sources.jar differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/pom.xml libjung-free-java-2.1.1/jung-samples/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-samples/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,90 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-samples + JUNG - Samples + + Sample programs using JUNG. Nearly all JUNG capabilities are demonstrated here. + Please study the source code for these examples prior to asking how to do something. + + + + + net.sf.jung + jung-api + ${project.version} + + + net.sf.jung + jung-visualization + ${project.version} + + + net.sf.jung + jung-graph-impl + ${project.version} + + + net.sf.jung + jung-algorithms + ${project.version} + + + net.sf.jung + jung-io + ${project.version} + + + + + + + maven-jar-plugin + + + + edu.uci.ics.jung.samples.VertexImageShaperDemo + true + + + + + + + + + + + assembly + + true + + + + + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory} + + + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/simple.graphml libjung-free-java-2.1.1/jung-samples/simple.graphml --- libjung-free-java-2.0.1+dfsg/jung-samples/simple.graphml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/simple.graphml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/assembly/assembly.xml libjung-free-java-2.1.1/jung-samples/src/main/assembly/assembly.xml --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/assembly/assembly.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/assembly/assembly.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + dependencies + + zip + + false + + + / + false + runtime + + + \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AddNodeDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AddNodeDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AddNodeDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AddNodeDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on May 10, 2004 + */ + + +package edu.uci.ics.jung.samples; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Timer; +import java.util.TimerTask; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JRootPane; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.AbstractLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout2; +import edu.uci.ics.jung.algorithms.layout.SpringLayout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.ObservableGraph; +import edu.uci.ics.jung.graph.event.GraphEvent; +import edu.uci.ics.jung.graph.event.GraphEventListener; +import edu.uci.ics.jung.graph.util.Graphs; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.Renderer; + +/** + * Demonstrates visualization of a graph being actively updated. + * + * @author danyelf + */ +public class AddNodeDemo extends javax.swing.JApplet { + + /** + * + */ + private static final long serialVersionUID = -5345319851341875800L; + + private Graph g = null; + + private VisualizationViewer vv = null; + + private AbstractLayout layout = null; + + Timer timer; + + boolean done; + + protected JButton switchLayout; + +// public static final LengthFunction UNITLENGTHFUNCTION = new SpringLayout.UnitLengthFunction( +// 100); + public static final int EDGE_LENGTH = 100; + + @Override + public void init() { + + //create a graph + Graph ig = Graphs.synchronizedDirectedGraph(new DirectedSparseMultigraph()); + + ObservableGraph og = new ObservableGraph(ig); + og.addGraphEventListener(new GraphEventListener() { + + public void handleGraphEvent(GraphEvent evt) { + System.err.println("got "+evt); + + }}); + this.g = og; + //create a graphdraw + layout = new FRLayout2(g); +// ((FRLayout)layout).setMaxIterations(200); + + vv = new VisualizationViewer(layout, new Dimension(600,600)); + + JRootPane rp = this.getRootPane(); + rp.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().setBackground(java.awt.Color.lightGray); + getContentPane().setFont(new Font("Serif", Font.PLAIN, 12)); + + vv.getModel().getRelaxer().setSleepTime(500); + vv.setGraphMouse(new DefaultModalGraphMouse()); + + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.setForeground(Color.white); + getContentPane().add(vv); + switchLayout = new JButton("Switch to SpringLayout"); + switchLayout.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent ae) { + Dimension d = new Dimension(600,600); + if (switchLayout.getText().indexOf("Spring") > 0) { + switchLayout.setText("Switch to FRLayout"); + layout = new SpringLayout(g, + Functions.constant(EDGE_LENGTH)); + layout.setSize(d); + vv.getModel().setGraphLayout(layout, d); + } else { + switchLayout.setText("Switch to SpringLayout"); + layout = new FRLayout(g, d); + vv.getModel().setGraphLayout(layout, d); + } + } + }); + + getContentPane().add(switchLayout, BorderLayout.SOUTH); + + timer = new Timer(); + } + + @Override + public void start() { + validate(); + //set timer so applet will change + timer.schedule(new RemindTask(), 1000, 1000); //subsequent rate + vv.repaint(); + } + + Integer v_prev = null; + + public void process() { + + try { + + if (g.getVertexCount() < 100) { + layout.lock(true); + //add a vertex + Integer v1 = new Integer(g.getVertexCount()); + + Relaxer relaxer = vv.getModel().getRelaxer(); + relaxer.pause(); + g.addVertex(v1); + System.err.println("added node " + v1); + + // wire it to some edges + if (v_prev != null) { + g.addEdge(g.getEdgeCount(), v_prev, v1); + // let's connect to a random vertex, too! + int rand = (int) (Math.random() * g.getVertexCount()); + g.addEdge(g.getEdgeCount(), v1, rand); + } + + v_prev = v1; + + layout.initialize(); + relaxer.resume(); + layout.lock(false); + } else { + done = true; + } + + } catch (Exception e) { + System.out.println(e); + + } + } + + class RemindTask extends TimerTask { + + @Override + public void run() { + process(); + if(done) cancel(); + + } + } + + public static void main(String[] args) { + AddNodeDemo and = new AddNodeDemo(); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(and); + + and.init(); + and.start(); + frame.pack(); + frame.setVisible(true); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnimatingAddNodeDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnimatingAddNodeDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnimatingAddNodeDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnimatingAddNodeDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ + + +package edu.uci.ics.jung.samples; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.util.Timer; +import java.util.TimerTask; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JRootPane; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.AbstractLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.algorithms.layout.util.VisRunner; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.ObservableGraph; +import edu.uci.ics.jung.graph.event.GraphEvent; +import edu.uci.ics.jung.graph.event.GraphEventListener; +import edu.uci.ics.jung.graph.util.Graphs; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.util.Animator; + +/** + * A variation of AddNodeDemo that animates transitions between graph states. + * + * @author Tom Nelson + */ +public class AnimatingAddNodeDemo extends javax.swing.JApplet { + + /** + * + */ + private static final long serialVersionUID = -5345319851341875800L; + + private Graph g = null; + + private VisualizationViewer vv = null; + + private AbstractLayout layout = null; + + Timer timer; + + boolean done; + + protected JButton switchLayout; + + public static final int EDGE_LENGTH = 100; + + @Override + public void init() { + + //create a graph + Graph ig = Graphs.synchronizedDirectedGraph(new DirectedSparseMultigraph()); + + ObservableGraph og = new ObservableGraph(ig); + og.addGraphEventListener(new GraphEventListener() { + + public void handleGraphEvent(GraphEvent evt) { + System.err.println("got "+evt); + + }}); + this.g = og; + //create a graphdraw + layout = new FRLayout(g); + layout.setSize(new Dimension(600,600)); + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.stop(); + relaxer.prerelax(); + + Layout staticLayout = + new StaticLayout(g, layout); + + vv = new VisualizationViewer(staticLayout, new Dimension(600,600)); + + JRootPane rp = this.getRootPane(); + rp.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().setBackground(java.awt.Color.lightGray); + getContentPane().setFont(new Font("Serif", Font.PLAIN, 12)); + + vv.setGraphMouse(new DefaultModalGraphMouse()); + + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.setForeground(Color.white); + + vv.addComponentListener(new ComponentAdapter() { + + /** + * @see java.awt.event.ComponentAdapter#componentResized(java.awt.event.ComponentEvent) + */ + @Override + public void componentResized(ComponentEvent arg0) { + super.componentResized(arg0); + System.err.println("resized"); + layout.setSize(arg0.getComponent().getSize()); + }}); + + getContentPane().add(vv); + switchLayout = new JButton("Switch to SpringLayout"); + switchLayout.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent ae) { + Dimension d = vv.getSize();//new Dimension(600,600); + if (switchLayout.getText().indexOf("Spring") > 0) { + switchLayout.setText("Switch to FRLayout"); + layout = + new SpringLayout(g, Functions.constant(EDGE_LENGTH)); + layout.setSize(d); + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.stop(); + relaxer.prerelax(); + StaticLayout staticLayout = + new StaticLayout(g, layout); + LayoutTransition lt = + new LayoutTransition(vv, vv.getGraphLayout(), + staticLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.repaint(); + + } else { + switchLayout.setText("Switch to SpringLayout"); + layout = new FRLayout(g, d); + layout.setSize(d); + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.stop(); + relaxer.prerelax(); + StaticLayout staticLayout = + new StaticLayout(g, layout); + LayoutTransition lt = + new LayoutTransition(vv, vv.getGraphLayout(), + staticLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.repaint(); + + } + } + }); + + getContentPane().add(switchLayout, BorderLayout.SOUTH); + + timer = new Timer(); + } + + @Override + public void start() { + validate(); + //set timer so applet will change + timer.schedule(new RemindTask(), 1000, 1000); //subsequent rate + vv.repaint(); + } + + Integer v_prev = null; + + public void process() { + + vv.getRenderContext().getPickedVertexState().clear(); + vv.getRenderContext().getPickedEdgeState().clear(); + try { + + if (g.getVertexCount() < 100) { + //add a vertex + Integer v1 = new Integer(g.getVertexCount()); + + g.addVertex(v1); + vv.getRenderContext().getPickedVertexState().pick(v1, true); + + // wire it to some edges + if (v_prev != null) { + Integer edge = g.getEdgeCount(); + vv.getRenderContext().getPickedEdgeState().pick(edge, true); + g.addEdge(edge, v_prev, v1); + // let's connect to a random vertex, too! + int rand = (int) (Math.random() * g.getVertexCount()); + edge = g.getEdgeCount(); + vv.getRenderContext().getPickedEdgeState().pick(edge, true); + g.addEdge(edge, v1, rand); + } + + v_prev = v1; + + layout.initialize(); + + Relaxer relaxer = new VisRunner((IterativeContext)layout); + relaxer.stop(); + relaxer.prerelax(); + StaticLayout staticLayout = + new StaticLayout(g, layout); + LayoutTransition lt = + new LayoutTransition(vv, vv.getGraphLayout(), + staticLayout); + Animator animator = new Animator(lt); + animator.start(); +// vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.repaint(); + + } else { + done = true; + } + + } catch (Exception e) { + System.out.println(e); + + } + } + + class RemindTask extends TimerTask { + + @Override + public void run() { + process(); + if(done) cancel(); + + } + } + + public static void main(String[] args) { + AnimatingAddNodeDemo and = new AnimatingAddNodeDemo(); + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().add(and); + + and.init(); + and.start(); + frame.pack(); + frame.setVisible(true); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnnotationsDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnnotationsDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnnotationsDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/AnnotationsDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.annotations.AnnotatingGraphMousePlugin; +import edu.uci.ics.jung.visualization.annotations.AnnotatingModalGraphMouse; +import edu.uci.ics.jung.visualization.annotations.AnnotationControls; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.Renderer; + +/** + * Demonstrates annotation of graph elements. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class AnnotationsDemo extends JApplet { + + static final String instructions = + ""+ + "

    Instructions for Annotations

    "+ + "

    The Annotation Controls allow you to select:"+ + "

      "+ + "
    • Shape"+ + "
    • Color"+ + "
    • Fill (or outline)"+ + "
    • Above or below (UPPER/LOWER) the graph display"+ + "
    "+ + "

    Mouse Button one press starts a Shape,"+ + "

    drag and release to complete."+ + "

    Mouse Button three pops up an input dialog"+ + "

    for text. This will create a text annotation."+ + "

    You may use html for multi-line, etc."+ + "

    You may even use an image tag and image url"+ + "

    to put an image in the annotation."+ + "

    "+ + "

    To remove an annotation, shift-click on it"+ + "

    in the Annotations mode."+ + "

    If there is overlap, the Annotation with center"+ + "

    closest to the mouse point will be removed."; + + JDialog helpDialog; + + Paintable viewGrid; + + /** + * create an instance of a simple graph in two views with controls to + * demo the features. + * + */ + public AnnotationsDemo() { + + // create a simple graph for the demo + Graph graph = TestGraphs.getOneComponentGraph(); + + // the preferred sizes for the two views + Dimension preferredSize1 = new Dimension(600,600); + + // create one layout for the graph + FRLayout layout = new FRLayout(graph); + layout.setMaxIterations(500); + + VisualizationModel vm = + new DefaultVisualizationModel(layout, preferredSize1); + + // create 2 views that share the same model + final VisualizationViewer vv = + new VisualizationViewer(vm, preferredSize1); + vv.setBackground(Color.white); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.red, Color.yellow)); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + + // add default listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + Container panel = new JPanel(new BorderLayout()); + + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + panel.add(gzsp); + + helpDialog = new JDialog(); + helpDialog.getContentPane().add(new JLabel(instructions)); + + RenderContext rc = vv.getRenderContext(); + AnnotatingGraphMousePlugin annotatingPlugin = + new AnnotatingGraphMousePlugin(rc); + // create a GraphMouse for the main view + // + final AnnotatingModalGraphMouse graphMouse = + new AnnotatingModalGraphMouse(rc, annotatingPlugin); + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.setSelectedItem(ModalGraphMouse.Mode.ANNOTATING); + + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + helpDialog.pack(); + helpDialog.setVisible(true); + } + }); + + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + controls.add(zoomControls); + + JPanel modeControls = new JPanel(); + modeControls.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modeControls.add(graphMouse.getModeComboBox()); + controls.add(modeControls); + + JPanel annotationControlPanel = new JPanel(); + annotationControlPanel.setBorder(BorderFactory.createTitledBorder("Annotation Controls")); + + AnnotationControls annotationControls = + new AnnotationControls(annotatingPlugin); + + annotationControlPanel.add(annotationControls.getAnnotationsToolBar()); + controls.add(annotationControlPanel); + + JPanel helpControls = new JPanel(); + helpControls.setBorder(BorderFactory.createTitledBorder("Help")); + helpControls.add(help); + controls.add(helpControls); + content.add(panel); + content.add(controls, BorderLayout.SOUTH); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new AnnotationsDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/BalloonLayoutDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/BalloonLayoutDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/BalloonLayoutDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/BalloonLayoutDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JToggleButton; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.BalloonLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.transform.LensSupport; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator; +import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport; +import edu.uci.ics.jung.visualization.util.Animator; + +/** + * Demonstrates the visualization of a Tree using TreeLayout + * and BalloonLayout. An examiner lens performing a hyperbolic + * transformation of the view is also included. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class BalloonLayoutDemo extends JApplet { + + /** + * the graph + */ + Forest graph; + + Supplier> graphFactory = + new Supplier>() { + + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + + Supplier> treeFactory = + new Supplier> () { + + public Tree get() { + return new DelegateTree(graphFactory); + } + }; + + Supplier edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + + Supplier vertexFactory = new Supplier() { + int i=0; + public String get() { + return "V"+i++; + }}; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + VisualizationServer.Paintable rings; + + String root; + + TreeLayout layout; + + BalloonLayout radialLayout; + /** + * provides a Hyperbolic lens for the view + */ + LensSupport hyperbolicViewSupport; + + public BalloonLayoutDemo() { + + // create a simple graph for the demo + graph = new DelegateForest(); + + createTree(); + + layout = new TreeLayout(graph); + radialLayout = new BalloonLayout(graph); + radialLayout.setSize(new Dimension(900,900)); + vv = new VisualizationViewer(layout, new Dimension(600,600)); + vv.setBackground(Color.white); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph)); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + rings = new Rings(radialLayout); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse = + new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + hyperbolicViewSupport = + new ViewLensSupport(vv, new HyperbolicShapeTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), + new ModalLensGraphMouse()); + + + graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener()); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + vv.scaleToLayout(scaler); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JToggleButton radial = new JToggleButton("Balloon"); + radial.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + + LayoutTransition lt = + new LayoutTransition(vv, layout, radialLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity(); + vv.addPreRenderPaintable(rings); + } else { + + LayoutTransition lt = + new LayoutTransition(vv, radialLayout, layout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity(); + vv.removePreRenderPaintable(rings); + } + vv.repaint(); + }}); + final JRadioButton hyperView = new JRadioButton("Hyperbolic View"); + hyperView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(radial); + controls.add(scaleGrid); + controls.add(modeBox); + controls.add(hyperView); + content.add(controls, BorderLayout.SOUTH); + } + + class Rings implements VisualizationServer.Paintable { + + BalloonLayout layout; + + public Rings(BalloonLayout layout) { + this.layout = layout; + } + + public void paint(Graphics g) { + g.setColor(Color.gray); + + Graphics2D g2d = (Graphics2D)g; + + Ellipse2D ellipse = new Ellipse2D.Double(); + for(String v : layout.getGraph().getVertices()) { + Double radius = layout.getRadii().get(v); + if(radius == null) continue; + Point2D p = layout.apply(v); + ellipse.setFrame(-radius, -radius, 2*radius, 2*radius); + AffineTransform at = AffineTransform.getTranslateInstance(p.getX(), p.getY()); + Shape shape = at.createTransformedShape(ellipse); + + MutableTransformer viewTransformer = + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + + if(viewTransformer instanceof MutableTransformerDecorator) { + shape = vv.getRenderContext().getMultiLayerTransformer().transform(shape); + } else { + shape = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT,shape); + } + + g2d.draw(shape); + } + } + + public boolean useTransform() { + return true; + } + } + + /** + * + */ + private void createTree() { + + graph.addVertex("A0"); + graph.addEdge(edgeFactory.get(), "A0", "B0"); + graph.addEdge(edgeFactory.get(), "A0", "B1"); + graph.addEdge(edgeFactory.get(), "A0", "B2"); + + graph.addEdge(edgeFactory.get(), "B0", "C0"); + graph.addEdge(edgeFactory.get(), "B0", "C1"); + graph.addEdge(edgeFactory.get(), "B0", "C2"); + graph.addEdge(edgeFactory.get(), "B0", "C3"); + + graph.addEdge(edgeFactory.get(), "C2", "H0"); + graph.addEdge(edgeFactory.get(), "C2", "H1"); + + graph.addEdge(edgeFactory.get(), "B1", "D0"); + graph.addEdge(edgeFactory.get(), "B1", "D1"); + graph.addEdge(edgeFactory.get(), "B1", "D2"); + + graph.addEdge(edgeFactory.get(), "B2", "E0"); + graph.addEdge(edgeFactory.get(), "B2", "E1"); + graph.addEdge(edgeFactory.get(), "B2", "E2"); + + graph.addEdge(edgeFactory.get(), "D0", "F0"); + graph.addEdge(edgeFactory.get(), "D0", "F1"); + graph.addEdge(edgeFactory.get(), "D0", "F2"); + + graph.addEdge(edgeFactory.get(), "D1", "G0"); + graph.addEdge(edgeFactory.get(), "D1", "G1"); + graph.addEdge(edgeFactory.get(), "D1", "G2"); + graph.addEdge(edgeFactory.get(), "D1", "G3"); + graph.addEdge(edgeFactory.get(), "D1", "G4"); + graph.addEdge(edgeFactory.get(), "D1", "G5"); + graph.addEdge(edgeFactory.get(), "D1", "G6"); + graph.addEdge(edgeFactory.get(), "D1", "G7"); + + // uncomment this to make it a Forest: +// graph.addVertex("K0"); +// graph.addEdge(edgeFactory.get(), "K0", "K1"); +// graph.addEdge(edgeFactory.get(), "K0", "K2"); +// graph.addEdge(edgeFactory.get(), "K0", "K3"); +// +// graph.addVertex("J0"); +// graph.addEdge(edgeFactory.get(), "J0", "J1"); +// graph.addEdge(edgeFactory.get(), "J0", "J2"); +// graph.addEdge(edgeFactory.get(), "J1", "J4"); +// graph.addEdge(edgeFactory.get(), "J2", "J3"); +//// graph.addEdge(edgeFactory.get(), "J2", "J5"); +//// graph.addEdge(edgeFactory.get(), "J4", "J6"); +//// graph.addEdge(edgeFactory.get(), "J4", "J7"); +//// graph.addEdge(edgeFactory.get(), "J3", "J8"); +//// graph.addEdge(edgeFactory.get(), "J6", "B9"); + + + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new BalloonLayoutDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ClusteringDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ClusteringDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ClusteringDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ClusteringDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,333 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.samples; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Point2D; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.JToggleButton; +import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.cluster.EdgeBetweennessClusterer; +import edu.uci.ics.jung.algorithms.layout.AggregateLayout; +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.io.PajekNetReader; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; + + +/** + * This simple app demonstrates how one can use our algorithms and visualization libraries in unison. + * In this case, we generate use the Zachary karate club data set, widely known in the social networks literature, then + * we cluster the vertices using an edge-betweenness clusterer, and finally we visualize the graph using + * Fruchtermain-Rheingold layout and provide a slider so that the user can adjust the clustering granularity. + * @author Scott White + */ +@SuppressWarnings("serial") +public class ClusteringDemo extends JApplet { + + VisualizationViewer vv; + + LoadingCache vertexPaints = + CacheBuilder.newBuilder().build( + CacheLoader.from(Functions.constant(Color.white))); + LoadingCache edgePaints = + CacheBuilder.newBuilder().build( + CacheLoader.from(Functions.constant(Color.blue))); + + public final Color[] similarColors = + { + new Color(216, 134, 134), + new Color(135, 137, 211), + new Color(134, 206, 189), + new Color(206, 176, 134), + new Color(194, 204, 134), + new Color(145, 214, 134), + new Color(133, 178, 209), + new Color(103, 148, 255), + new Color(60, 220, 220), + new Color(30, 250, 100) + }; + + public static void main(String[] args) throws IOException { + + ClusteringDemo cd = new ClusteringDemo(); + cd.start(); + // Add a restart button so the graph can be redrawn to fit the size of the frame + JFrame jf = new JFrame(); + jf.getContentPane().add(cd); + + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.pack(); + jf.setVisible(true); + } + + public void start() { + InputStream is = this.getClass().getClassLoader().getResourceAsStream("datasets/zachary.net"); + BufferedReader br = new BufferedReader( new InputStreamReader( is )); + + try + { + setUpView(br); + } + catch (IOException e) + { + System.out.println("Error in loading graph"); + e.printStackTrace(); + } + } + + private void setUpView(BufferedReader br) throws IOException { + + Supplier vertexFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + Supplier edgeFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + + PajekNetReader, Number,Number> pnr = + new PajekNetReader, Number,Number>(vertexFactory, edgeFactory); + + final Graph graph = new SparseMultigraph(); + + pnr.load(br, graph); + + //Create a simple layout frame + //specify the Fruchterman-Rheingold layout algorithm + final AggregateLayout layout = + new AggregateLayout(new FRLayout(graph)); + + vv = new VisualizationViewer(layout); + vv.setBackground( Color.white ); + //Tell the renderer to use our own customized color rendering + vv.getRenderContext().setVertexFillPaintTransformer(vertexPaints); + vv.getRenderContext().setVertexDrawPaintTransformer(new Function() { + public Paint apply(Number v) { + if(vv.getPickedVertexState().isPicked(v)) { + return Color.cyan; + } else { + return Color.BLACK; + } + } + }); + + vv.getRenderContext().setEdgeDrawPaintTransformer(edgePaints); + + vv.getRenderContext().setEdgeStrokeTransformer(new Function() { + protected final Stroke THIN = new BasicStroke(1); + protected final Stroke THICK= new BasicStroke(2); + public Stroke apply(Number e) + { + Paint c = edgePaints.getUnchecked(e); + if (c == Color.LIGHT_GRAY) + return THIN; + else + return THICK; + } + }); + + //add restart button + JButton scramble = new JButton("Restart"); + scramble.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + Layout layout = vv.getGraphLayout(); + layout.initialize(); + Relaxer relaxer = vv.getModel().getRelaxer(); + if(relaxer != null) { + relaxer.stop(); + relaxer.prerelax(); + relaxer.relax(); + } + } + + }); + + DefaultModalGraphMouse gm = new DefaultModalGraphMouse(); + vv.setGraphMouse(gm); + + final JToggleButton groupVertices = new JToggleButton("Group Clusters"); + + //Create slider to adjust the number of edges to remove when clustering + final JSlider edgeBetweennessSlider = new JSlider(JSlider.HORIZONTAL); + edgeBetweennessSlider.setBackground(Color.WHITE); + edgeBetweennessSlider.setPreferredSize(new Dimension(210, 50)); + edgeBetweennessSlider.setPaintTicks(true); + edgeBetweennessSlider.setMaximum(graph.getEdgeCount()); + edgeBetweennessSlider.setMinimum(0); + edgeBetweennessSlider.setValue(0); + edgeBetweennessSlider.setMajorTickSpacing(10); + edgeBetweennessSlider.setPaintLabels(true); + edgeBetweennessSlider.setPaintTicks(true); + +// edgeBetweennessSlider.setBorder(BorderFactory.createLineBorder(Color.black)); + //TO DO: edgeBetweennessSlider.add(new JLabel("Node Size (PageRank With Priors):")); + //I also want the slider value to appear + final JPanel eastControls = new JPanel(); + eastControls.setOpaque(true); + eastControls.setLayout(new BoxLayout(eastControls, BoxLayout.Y_AXIS)); + eastControls.add(Box.createVerticalGlue()); + eastControls.add(edgeBetweennessSlider); + + final String COMMANDSTRING = "Edges removed for clusters: "; + final String eastSize = COMMANDSTRING + edgeBetweennessSlider.getValue(); + + final TitledBorder sliderBorder = BorderFactory.createTitledBorder(eastSize); + eastControls.setBorder(sliderBorder); + //eastControls.add(eastSize); + eastControls.add(Box.createVerticalGlue()); + + groupVertices.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + clusterAndRecolor(layout, edgeBetweennessSlider.getValue(), + similarColors, e.getStateChange() == ItemEvent.SELECTED); + vv.repaint(); + }}); + + + clusterAndRecolor(layout, 0, similarColors, groupVertices.isSelected()); + + edgeBetweennessSlider.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + JSlider source = (JSlider) e.getSource(); + if (!source.getValueIsAdjusting()) { + int numEdgesToRemove = source.getValue(); + clusterAndRecolor(layout, numEdgesToRemove, similarColors, + groupVertices.isSelected()); + sliderBorder.setTitle( + COMMANDSTRING + edgeBetweennessSlider.getValue()); + eastControls.repaint(); + vv.validate(); + vv.repaint(); + } + } + }); + + Container content = getContentPane(); + content.add(new GraphZoomScrollPane(vv)); + JPanel south = new JPanel(); + JPanel grid = new JPanel(new GridLayout(2,1)); + grid.add(scramble); + grid.add(groupVertices); + south.add(grid); + south.add(eastControls); + JPanel p = new JPanel(); + p.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + p.add(gm.getModeComboBox()); + south.add(p); + content.add(south, BorderLayout.SOUTH); + } + + public void clusterAndRecolor(AggregateLayout layout, + int numEdgesToRemove, + Color[] colors, boolean groupClusters) { + //Now cluster the vertices by removing the top 50 edges with highest betweenness + // if (numEdgesToRemove == 0) { + // colorCluster( g.getVertices(), colors[0] ); + // } else { + + Graph g = layout.getGraph(); + layout.removeAll(); + + EdgeBetweennessClusterer clusterer = + new EdgeBetweennessClusterer(numEdgesToRemove); + Set> clusterSet = clusterer.apply(g); + List edges = clusterer.getEdgesRemoved(); + + int i = 0; + //Set the colors of each node so that each cluster's vertices have the same color + for (Iterator> cIt = clusterSet.iterator(); cIt.hasNext();) { + + Set vertices = cIt.next(); + Color c = colors[i % colors.length]; + + colorCluster(vertices, c); + if(groupClusters == true) { + groupCluster(layout, vertices); + } + i++; + } + for (Number e : g.getEdges()) { + + if (edges.contains(e)) { + edgePaints.put(e, Color.lightGray); + } else { + edgePaints.put(e, Color.black); + } + } + + } + + private void colorCluster(Set vertices, Color c) { + for (Number v : vertices) { + vertexPaints.put(v, c); + } + } + + private void groupCluster(AggregateLayout layout, Set vertices) { + if(vertices.size() < layout.getGraph().getVertexCount()) { + Point2D center = layout.apply(vertices.iterator().next()); + Graph subGraph = SparseMultigraph.getFactory().get(); + for(Number v : vertices) { + subGraph.addVertex(v); + } + Layout subLayout = + new CircleLayout(subGraph); + subLayout.setInitializer(vv.getGraphLayout()); + subLayout.setSize(new Dimension(40,40)); + + layout.put(subLayout,center); + vv.repaint(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/DemoLensVertexImageShaperDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/DemoLensVertexImageShaperDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/DemoLensVertexImageShaperDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/DemoLensVertexImageShaperDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.LayeredIcon; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.decorators.VertexIconShapeTransformer; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.Checkmark; +import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; +import edu.uci.ics.jung.visualization.transform.LayoutLensSupport; +import edu.uci.ics.jung.visualization.transform.LensSupport; +import edu.uci.ics.jung.visualization.transform.shape.MagnifyImageLensSupport; + + +/** + * Demonstrates the use of images to represent graph vertices. + * The images are added to the DefaultGraphLabelRenderer and can + * either be offset from the vertex, or centered on the vertex. + * Additionally, the relative positioning of the label and + * image is controlled by subclassing the DefaultGraphLabelRenderer + * and setting the appropriate properties on its JLabel superclass + * FancyGraphLabelRenderer + * + * The images used in this demo (courtesy of slashdot.org) are + * rectangular but with a transparent background. When vertices + * are represented by these images, it looks better if the actual + * shape of the opaque part of the image is computed so that the + * edge arrowheads follow the visual shape of the image. This demo + * uses the FourPassImageShaper class to compute the Shape from + * an image with transparent background. + * + * @author Tom Nelson + * + */ +public class DemoLensVertexImageShaperDemo extends JApplet { + + /** + * + */ + private static final long serialVersionUID = 5432239991020505763L; + + /** + * the graph + */ + DirectedSparseGraph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * some icon names to use + */ + String[] iconNames = { + "sample2" + }; + + LensSupport viewSupport; + LensSupport modelSupport; + LensSupport magnifyLayoutSupport; + LensSupport magnifyViewSupport; + /** + * create an instance of a simple graph with controls to + * demo the zoom features. + * + */ + public DemoLensVertexImageShaperDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + Number[] vertices = createVertices(1); + + // a Map for the labels + Map map = new HashMap(); + for(int i=0; i iconMap = new HashMap(); + for(int i=0; i layout = new FRLayout(graph); + layout.setMaxIterations(100); + vv = new VisualizationViewer(layout, new Dimension(600,600)); + + Function vpf = + new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.white, Color.yellow); + vv.getRenderContext().setVertexFillPaintTransformer(vpf); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + + vv.setBackground(Color.white); + + final Function vertexStringerImpl = + new VertexStringerImpl(map); + vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); + + + // features on and off. For a real application, use VertexIconAndShapeFunction instead. + final VertexIconShapeTransformer vertexImageShapeFunction = + new VertexIconShapeTransformer(new EllipseVertexShapeTransformer()); + vertexImageShapeFunction.setIconMap(iconMap); + + final Function vertexIconFunction = Functions.forMap(iconMap); + + vv.getRenderContext().setVertexShapeTransformer(vertexImageShapeFunction); + vv.getRenderContext().setVertexIconTransformer(vertexIconFunction); + + // Get the pickedState and add a listener that will decorate the + // Vertex images with a checkmark icon when they are picked + PickedState ps = vv.getPickedVertexState(); + ps.addItemListener(new PickWithIconListener(vertexIconFunction)); + + vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){ + int x; + int y; + Font font; + FontMetrics metrics; + int swidth; + int sheight; + String str = "Thank You, slashdot.org, for the images!"; + + public void paint(Graphics g) { + Dimension d = vv.getSize(); + if(font == null) { + font = new Font(g.getFont().getName(), Font.BOLD, 20); + metrics = g.getFontMetrics(font); + swidth = metrics.stringWidth(str); + sheight = metrics.getMaxAscent()+metrics.getMaxDescent(); + x = (d.width-swidth)/2; + y = (int)(d.height-sheight*1.5); + } + g.setFont(font); + Color oldColor = g.getColor(); + g.setColor(Color.lightGray); + g.drawString(str, x, y); + g.setColor(oldColor); + } + public boolean useTransform() { + return false; + } + }); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(scaleGrid); + + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + + this.viewSupport = new MagnifyImageLensSupport(vv); +// new ViewLensSupport(vv, new HyperbolicShapeTransformer(vv, +// vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), +// new ModalLensGraphMouse()); + + this.modelSupport = new LayoutLensSupport(vv); + + graphMouse.addItemListener(modelSupport.getGraphMouse().getModeListener()); + graphMouse.addItemListener(viewSupport.getGraphMouse().getModeListener()); + + ButtonGroup radio = new ButtonGroup(); + JRadioButton none = new JRadioButton("None"); + none.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(viewSupport != null) { + viewSupport.deactivate(); + } + if(modelSupport != null) { + modelSupport.deactivate(); + } + } + }); + none.setSelected(true); + + JRadioButton hyperView = new JRadioButton("View"); + hyperView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + viewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + + JRadioButton hyperModel = new JRadioButton("Layout"); + hyperModel.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + modelSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + radio.add(none); + radio.add(hyperView); + radio.add(hyperModel); + + JMenuBar menubar = new JMenuBar(); + JMenu modeMenu = graphMouse.getModeMenu(); + menubar.add(modeMenu); + + JPanel lensPanel = new JPanel(new GridLayout(2,0)); + lensPanel.setBorder(BorderFactory.createTitledBorder("Lens")); + lensPanel.add(none); + lensPanel.add(hyperView); + lensPanel.add(hyperModel); + controls.add(lensPanel); + } + + /** + * A simple implementation of VertexStringer that + * gets Vertex labels from a Map + * + * @author Tom Nelson + * + * + */ + class VertexStringerImpl implements Function { + + Map map = new HashMap(); + + boolean enabled = true; + + public VertexStringerImpl(Map map) { + this.map = map; + } + + /** + * @see edu.uci.ics.jung.graph.decorators.VertexStringer#getLabel(edu.uci.ics.jung.graph.Vertex) + */ + public String apply(V v) { + if(isEnabled()) { + return map.get(v); + } else { + return ""; + } + } + + /** + * @return Returns the enabled. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * @param enabled The enabled to set. + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private Number[] createVertices(int count) { + Number[] v = new Number[count]; + for (int i = 0; i < count; i++) { + v[i] = new Integer(i); + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(Number[] v) { +// graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[3], v[0], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[5], v[3], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[2], v[1], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[4], v[1], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[4], v[10], EdgeType.DIRECTED); +// graph.addEdge(new Double(Math.random()), v[10], v[4], EdgeType.DIRECTED); + } + + public static class PickWithIconListener implements ItemListener { + Function imager; + Icon checked; + + public PickWithIconListener(Function imager) { + this.imager = imager; + checked = new Checkmark(Color.red); + } + + public void itemStateChanged(ItemEvent e) { + Icon icon = imager.apply((Number)e.getItem()); + if(icon != null && icon instanceof LayeredIcon) { + if(e.getStateChange() == ItemEvent.SELECTED) { + ((LayeredIcon)icon).add(checked); + } else { + ((LayeredIcon)icon).remove(checked); + } + } + } + } + + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new DemoLensVertexImageShaperDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/DrawnIconVertexDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/DrawnIconVertexDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/DrawnIconVertexDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/DrawnIconVertexDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; + +/** + * A demo that shows drawn Icons as vertices + * + * @author Tom Nelson + * + */ +public class DrawnIconVertexDemo { + + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + public DrawnIconVertexDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + Integer[] v = createVertices(10); + createEdges(v); + + vv = new VisualizationViewer(new FRLayout(graph)); + vv.getRenderContext().setVertexLabelTransformer(new Function(){ + + public String apply(Integer v) { + return "Vertex "+v; + }}); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); + + vv.getRenderContext().setVertexIconTransformer(new Function() { + + /* + * Implements the Icon interface to draw an Icon with background color and + * a text label + */ + public Icon apply(final Integer v) { + return new Icon() { + + public int getIconHeight() { + return 20; + } + + public int getIconWidth() { + return 20; + } + + public void paintIcon(Component c, Graphics g, + int x, int y) { + if(vv.getPickedVertexState().isPicked(v)) { + g.setColor(Color.yellow); + } else { + g.setColor(Color.red); + } + g.fillOval(x, y, 20, 20); + if(vv.getPickedVertexState().isPicked(v)) { + g.setColor(Color.black); + } else { + g.setColor(Color.white); + } + g.drawString(""+v, x+6, y+15); + + }}; + }}); + + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.white, Color.yellow)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.lightGray)); + + vv.setBackground(Color.white); + + // add my listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + final DefaultModalGraphMouse gm + = new DefaultModalGraphMouse(); + vv.setGraphMouse(gm); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + controls.add(gm.getModeComboBox()); + content.add(controls, BorderLayout.SOUTH); + + frame.pack(); + frame.setVisible(true); + } + + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private Integer[] createVertices(int count) { + Integer[] v = new Integer[count]; + for (int i = 0; i < count; i++) { + v[i] = new Integer(i); + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(Integer[] v) { + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[3], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED); + } + + public static void main(String[] args) + { + new DrawnIconVertexDemo(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/EdgeLabelDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/EdgeLabelDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/EdgeLabelDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/EdgeLabelDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.AbstractButton; +import javax.swing.BorderFactory; +import javax.swing.BoundedRangeModel; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.DefaultBoundedRangeModel; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ParallelEdgeShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.ConstantDirectionalEdgeValueTransformer; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.EdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.VertexLabelRenderer; + +/** + * Demonstrates jung support for drawing edge labels that + * can be positioned at any point along the edge, and can + * be rotated to be parallel with the edge. + * + * @author Tom Nelson + * + */ +public class EdgeLabelDemo extends JApplet { + private static final long serialVersionUID = -6077157664507049647L; + + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + */ + VertexLabelRenderer vertexLabelRenderer; + EdgeLabelRenderer edgeLabelRenderer; + + ScalingControl scaler = new CrossoverScalingControl(); + + /** + * create an instance of a simple graph with controls to + * demo the label positioning features + * + */ + @SuppressWarnings("serial") + public EdgeLabelDemo() { + + // create a simple graph for the demo + graph = new SparseMultigraph(); + Integer[] v = createVertices(3); + createEdges(v); + + Layout layout = new CircleLayout(graph); + vv = new VisualizationViewer(layout, new Dimension(600,400)); + vv.setBackground(Color.white); + + vertexLabelRenderer = vv.getRenderContext().getVertexLabelRenderer(); + edgeLabelRenderer = vv.getRenderContext().getEdgeLabelRenderer(); + + Function stringer = new Function(){ + public String apply(Number e) { + return "Edge:"+graph.getEndpoints(e).toString(); + } + }; + vv.getRenderContext().setEdgeLabelTransformer(stringer); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.red, Color.yellow)); + // add my listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + // create a frome to hold the graph + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + Container content = getContentPane(); + content.add(panel); + + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + ButtonGroup radio = new ButtonGroup(); + JRadioButton lineButton = new JRadioButton("Line"); + lineButton.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + vv.repaint(); + } + } + }); + + JRadioButton quadButton = new JRadioButton("QuadCurve"); + quadButton.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph)); + vv.repaint(); + } + } + }); + + JRadioButton cubicButton = new JRadioButton("CubicCurve"); + cubicButton.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.cubicCurve(graph)); + vv.repaint(); + } + } + }); + radio.add(lineButton); + radio.add(quadButton); + radio.add(cubicButton); + + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + JCheckBox rotate = new JCheckBox("

    EdgeType

    Parallel

    "); + rotate.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + AbstractButton b = (AbstractButton)e.getSource(); + edgeLabelRenderer.setRotateEdgeLabels(b.isSelected()); + vv.repaint(); + } + }); + rotate.setSelected(true); + MutableDirectionalEdgeValue mv = new MutableDirectionalEdgeValue(.5, .7); + vv.getRenderContext().setEdgeLabelClosenessTransformer(mv); + JSlider directedSlider = new JSlider(mv.getDirectedModel()) { + public Dimension getPreferredSize() { + Dimension d = super.getPreferredSize(); + d.width /= 2; + return d; + } + }; + JSlider undirectedSlider = new JSlider(mv.getUndirectedModel()) { + public Dimension getPreferredSize() { + Dimension d = super.getPreferredSize(); + d.width /= 2; + return d; + } + }; + + JSlider edgeOffsetSlider = new JSlider(0,50) { + public Dimension getPreferredSize() { + Dimension d = super.getPreferredSize(); + d.width /= 2; + return d; + } + }; + edgeOffsetSlider.addChangeListener(new ChangeListener() { + @SuppressWarnings("rawtypes") + public void stateChanged(ChangeEvent e) { + JSlider s = (JSlider)e.getSource(); + Function edgeShapeFunction + = vv.getRenderContext().getEdgeShapeTransformer(); + if (edgeShapeFunction instanceof ParallelEdgeShapeTransformer) { + ((ParallelEdgeShapeTransformer)edgeShapeFunction) + .setControlOffsetIncrement(s.getValue()); + vv.repaint(); + } + } + }); + + Box controls = Box.createHorizontalBox(); + + JPanel zoomPanel = new JPanel(new GridLayout(0,1)); + zoomPanel.setBorder(BorderFactory.createTitledBorder("Scale")); + zoomPanel.add(plus); + zoomPanel.add(minus); + + JPanel edgePanel = new JPanel(new GridLayout(0,1)); + edgePanel.setBorder(BorderFactory.createTitledBorder("EdgeType Type")); + edgePanel.add(lineButton); + edgePanel.add(quadButton); + edgePanel.add(cubicButton); + + JPanel rotatePanel = new JPanel(); + rotatePanel.setBorder(BorderFactory.createTitledBorder("Alignment")); + rotatePanel.add(rotate); + + JPanel labelPanel = new JPanel(new BorderLayout()); + JPanel sliderPanel = new JPanel(new GridLayout(3,1)); + JPanel sliderLabelPanel = new JPanel(new GridLayout(3,1)); + JPanel offsetPanel = new JPanel(new BorderLayout()); + offsetPanel.setBorder(BorderFactory.createTitledBorder("Offset")); + sliderPanel.add(directedSlider); + sliderPanel.add(undirectedSlider); + sliderPanel.add(edgeOffsetSlider); + sliderLabelPanel.add(new JLabel("Directed", JLabel.RIGHT)); + sliderLabelPanel.add(new JLabel("Undirected", JLabel.RIGHT)); + sliderLabelPanel.add(new JLabel("Edges", JLabel.RIGHT)); + offsetPanel.add(sliderLabelPanel, BorderLayout.WEST); + offsetPanel.add(sliderPanel); + labelPanel.add(offsetPanel); + labelPanel.add(rotatePanel, BorderLayout.WEST); + + JPanel modePanel = new JPanel(new GridLayout(2,1)); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(graphMouse.getModeComboBox()); + + controls.add(zoomPanel); + controls.add(edgePanel); + controls.add(labelPanel); + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + quadButton.setSelected(true); + } + + /** + * subclassed to hold two BoundedRangeModel instances that + * are used by JSliders to move the edge label positions + * @author Tom Nelson + * + * + */ + class MutableDirectionalEdgeValue extends ConstantDirectionalEdgeValueTransformer { + BoundedRangeModel undirectedModel = new DefaultBoundedRangeModel(5,0,0,10); + BoundedRangeModel directedModel = new DefaultBoundedRangeModel(7,0,0,10); + + public MutableDirectionalEdgeValue(double undirected, double directed) { + super(undirected, directed); + undirectedModel.setValue((int)(undirected*10)); + directedModel.setValue((int)(directed*10)); + + undirectedModel.addChangeListener(new ChangeListener(){ + public void stateChanged(ChangeEvent e) { + setUndirectedValue(new Double(undirectedModel.getValue()/10f)); + vv.repaint(); + } + }); + directedModel.addChangeListener(new ChangeListener(){ + public void stateChanged(ChangeEvent e) { + setDirectedValue(new Double(directedModel.getValue()/10f)); + vv.repaint(); + } + }); + } + /** + * @return Returns the directedModel. + */ + public BoundedRangeModel getDirectedModel() { + return directedModel; + } + + /** + * @return Returns the undirectedModel. + */ + public BoundedRangeModel getUndirectedModel() { + return undirectedModel; + } + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private Integer[] createVertices(int count) { + Integer[] v = new Integer[count]; + for (int i = 0; i < count; i++) { + v[i] = new Integer(i); + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(Integer[] v) { + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[0], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[0], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[2]); + graph.addEdge(new Double(Math.random()), v[1], v[2]); + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + Container content = frame.getContentPane(); + content.add(new EdgeLabelDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphEditorDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphEditorDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphEditorDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphEditorDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.awt.print.Printable; +import java.awt.print.PrinterJob; +import java.io.File; + +import javax.imageio.ImageIO; +import javax.swing.AbstractAction; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.AbstractLayout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.annotations.AnnotationControls; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; + +/** + * Shows how to create a graph editor with JUNG. + * Mouse modes and actions are explained in the help text. + * The application version of GraphEditorDemo provides a + * File menu with an option to save the visible graph as + * a jpeg file. + * + * @author Tom Nelson + * + */ +public class GraphEditorDemo extends JApplet implements Printable { + + /** + * + */ + private static final long serialVersionUID = -2023243689258876709L; + + /** + * the graph + */ + Graph graph; + + AbstractLayout layout; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + String instructions = + ""+ + "

    All Modes:

    "+ + "
      "+ + "
    • Right-click an empty area for Create Vertex popup"+ + "
    • Right-click on a Vertex for Delete Vertex popup"+ + "
    • Right-click on a Vertex for Add Edge menus
      (if there are selected Vertices)"+ + "
    • Right-click on an Edge for Delete Edge popup"+ + "
    • Mousewheel scales with a crossover value of 1.0.

      "+ + " - scales the graph layout when the combined scale is greater than 1

      "+ + " - scales the graph view when the combined scale is less than 1"+ + + "

    "+ + "

    Editing Mode:

    "+ + "
      "+ + "
    • Left-click an empty area to create a new Vertex"+ + "
    • Left-click on a Vertex and drag to another Vertex to create an Undirected Edge"+ + "
    • Shift+Left-click on a Vertex and drag to another Vertex to create a Directed Edge"+ + "
    "+ + "

    Picking Mode:

    "+ + "
      "+ + "
    • Mouse1 on a Vertex selects the vertex"+ + "
    • Mouse1 elsewhere unselects all Vertices"+ + "
    • Mouse1+Shift on a Vertex adds/removes Vertex selection"+ + "
    • Mouse1+drag on a Vertex moves all selected Vertices"+ + "
    • Mouse1+drag elsewhere selects Vertices in a region"+ + "
    • Mouse1+Shift+drag adds selection of Vertices in a new region"+ + "
    • Mouse1+CTRL on a Vertex selects the vertex and centers the display on it"+ + "
    • Mouse1 double-click on a vertex or edge allows you to edit the label"+ + "
    "+ + "

    Transforming Mode:

    "+ + "
      "+ + "
    • Mouse1+drag pans the graph"+ + "
    • Mouse1+Shift+drag rotates the graph"+ + "
    • Mouse1+CTRL(or Command)+drag shears the graph"+ + "
    • Mouse1 double-click on a vertex or edge allows you to edit the label"+ + "
    "+ + "

    Annotation Mode:

    "+ + "
      "+ + "
    • Mouse1 begins drawing of a Rectangle"+ + "
    • Mouse1+drag defines the Rectangle shape"+ + "
    • Mouse1 release adds the Rectangle as an annotation"+ + "
    • Mouse1+Shift begins drawing of an Ellipse"+ + "
    • Mouse1+Shift+drag defines the Ellipse shape"+ + "
    • Mouse1+Shift release adds the Ellipse as an annotation"+ + "
    • Mouse3 shows a popup to input text, which will become"+ + "
    • a text annotation on the graph at the mouse location"+ + "
    "+ + ""; + + /** + * create an instance of a simple graph with popup controls to + * create a graph. + * + */ + public GraphEditorDemo() { + + // create a simple graph for the demo + graph = new SparseMultigraph(); + + this.layout = new StaticLayout(graph, + new Dimension(600,600)); + + vv = new VisualizationViewer(layout); + vv.setBackground(Color.white); + + Function labeller = new ToStringLabeller(); + vv.getRenderContext().setVertexLabelTransformer(labeller); + vv.getRenderContext().setEdgeLabelTransformer(labeller); + + vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer()); + + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + Supplier vertexFactory = new VertexFactory(); + Supplier edgeFactory = new EdgeFactory(); + + final EditingModalGraphMouse graphMouse = + new EditingModalGraphMouse(vv.getRenderContext(), vertexFactory, edgeFactory); + + // the EditingGraphMouse will pass mouse event coordinates to the + // vertexLocations function to set the locations of the vertices as + // they are created +// graphMouse.setVertexLocations(vertexLocations); + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + graphMouse.setMode(ModalGraphMouse.Mode.EDITING); + + final ScalingControl scaler = new CrossoverScalingControl(); + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog(vv, instructions); + }}); + + AnnotationControls annotationControls = + new AnnotationControls(graphMouse.getAnnotatingPlugin()); + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + JComboBox modeBox = graphMouse.getModeComboBox(); + controls.add(modeBox); + controls.add(annotationControls.getAnnotationsToolBar()); + controls.add(help); + content.add(controls, BorderLayout.SOUTH); + } + + /** + * copy the visible part of the graph to a file as a jpeg image + * @param file the file in which to save the graph image + */ + public void writeJPEGImage(File file) { + int width = vv.getWidth(); + int height = vv.getHeight(); + + BufferedImage bi = new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = bi.createGraphics(); + vv.paint(graphics); + graphics.dispose(); + + try { + ImageIO.write(bi, "jpeg", file); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public int print(java.awt.Graphics graphics, + java.awt.print.PageFormat pageFormat, int pageIndex) + throws java.awt.print.PrinterException { + if (pageIndex > 0) { + return (Printable.NO_SUCH_PAGE); + } else { + java.awt.Graphics2D g2d = (java.awt.Graphics2D) graphics; + vv.setDoubleBuffered(false); + g2d.translate(pageFormat.getImageableX(), pageFormat + .getImageableY()); + + vv.paint(g2d); + vv.setDoubleBuffered(true); + + return (Printable.PAGE_EXISTS); + } + } + + class VertexFactory implements Supplier { + + int i=0; + + public Number get() { + return i++; + } + } + + class EdgeFactory implements Supplier { + + int i=0; + + public Number get() { + return i++; + } + } + + @SuppressWarnings("serial") + public static void main(String[] args) { + JFrame frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + final GraphEditorDemo demo = new GraphEditorDemo(); + + JMenu menu = new JMenu("File"); + menu.add(new AbstractAction("Make Image") { + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + int option = chooser.showSaveDialog(demo); + if(option == JFileChooser.APPROVE_OPTION) { + File file = chooser.getSelectedFile(); + demo.writeJPEGImage(file); + } + }}); + menu.add(new AbstractAction("Print") { + public void actionPerformed(ActionEvent e) { + PrinterJob printJob = PrinterJob.getPrinterJob(); + printJob.setPrintable(demo); + if (printJob.printDialog()) { + try { + printJob.print(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }}); + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + frame.setJMenuBar(menuBar); + frame.getContentPane().add(demo); + frame.pack(); + frame.setVisible(true); + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphFromGraphMLDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphFromGraphMLDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphFromGraphMLDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphFromGraphMLDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.io.IOException; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JPanel; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.SAXException; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.io.GraphMLReader; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.GraphMouseListener; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner; + + +/** + * Demonstrates loading (and visualizing) a graph from a GraphML file. + * + * @author Tom Nelson + * + */ +public class GraphFromGraphMLDemo { + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * Creates an instance showing a simple graph with controls to demonstrate the zoom features. + * @param filename the file containing the graph data we're reading + * @throws ParserConfigurationException if a SAX parser cannot be constructed + * @throws SAXException if the SAX parser factory cannot be constructed + * @throws IOException if the file cannot be read + */ + public GraphFromGraphMLDemo(String filename) throws ParserConfigurationException, SAXException, IOException { + + Supplier vertexFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + Supplier edgeFactory = new Supplier() { + int n = 0; + public Number get() { return n++; } + }; + + GraphMLReader, Number, Number> gmlr = + new GraphMLReader, Number, Number>(vertexFactory, edgeFactory); + final DirectedGraph graph = new DirectedSparseMultigraph(); + gmlr.load(filename, graph); + + // create a simple graph for the demo + vv = new VisualizationViewer(new FRLayout(graph)); + + vv.addGraphMouseListener(new TestGraphMouseListener()); + vv.getRenderer().setVertexRenderer( + new GradientVertexRenderer( + Color.white, Color.red, + Color.white, Color.blue, + vv.getPickedVertexState(), + false)); + + // add my listeners for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.setEdgeToolTipTransformer(new Function() { + public String apply(Number edge) { + return "E"+graph.getEndpoints(edge).toString(); + }}); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner()); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + JMenuBar menubar = new JMenuBar(); + menubar.add(graphMouse.getModeMenu()); + panel.setCorner(menubar); + + + vv.addKeyListener(graphMouse.getModeKeyListener()); + vv.setToolTipText("
    Type 'p' for Pick mode

    Type 't' for Transform mode"); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + content.add(controls, BorderLayout.SOUTH); + + frame.pack(); + frame.setVisible(true); + } + + /** + * A nested class to demo the GraphMouseListener finding the + * right vertices after zoom/pan + */ + static class TestGraphMouseListener implements GraphMouseListener { + + public void graphClicked(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was clicked at ("+me.getX()+","+me.getY()+")"); + } + public void graphPressed(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was pressed at ("+me.getX()+","+me.getY()+")"); + } + public void graphReleased(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was released at ("+me.getX()+","+me.getY()+")"); + } + } + + /** + * @param args if this contains at least one element, the first will be used as the file to read + * @throws ParserConfigurationException if a SAX parser cannot be constructed + * @throws SAXException if the SAX parser factory cannot be constructed + * @throws IOException if the file cannot be read + */ + public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException + { + String filename = "simple.graphml"; + if(args.length > 0) filename = args[0]; + new GraphFromGraphMLDemo(filename); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphZoomScrollPaneDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphZoomScrollPaneDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphZoomScrollPaneDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/GraphZoomScrollPaneDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Paint; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.GraphMouseListener; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner; + + +/** + * Demonstrates the use of GraphZoomScrollPane. + * This class shows the VisualizationViewer zooming + * and panning capabilities, using horizontal and + * vertical scrollbars. + * + *

    This demo also shows ToolTips on graph vertices and edges, + * and a key listener to change graph mouse modes. + * + * @author Tom Nelson + * + */ +public class GraphZoomScrollPaneDemo { + + /** + * the graph + */ + DirectedSparseGraph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * create an instance of a simple graph with controls to + * demo the zoom features. + * + */ + public GraphZoomScrollPaneDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + String[] v = createVertices(10); + createEdges(v); + + ImageIcon sandstoneIcon = null; + String imageLocation = "/images/Sandstone.jpg"; + try { + sandstoneIcon = + new ImageIcon(getClass().getResource(imageLocation)); + } catch(Exception ex) { + System.err.println("Can't load \""+imageLocation+"\""); + } + final ImageIcon icon = sandstoneIcon; + vv = new VisualizationViewer(new KKLayout(graph)); + + if(icon != null) { + vv.addPreRenderPaintable(new VisualizationViewer.Paintable(){ + public void paint(Graphics g) { + Dimension d = vv.getSize(); + g.drawImage(icon.getImage(),0,0,d.width,d.height,vv); + } + public boolean useTransform() { return false; } + }); + } + vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){ + int x; + int y; + Font font; + FontMetrics metrics; + int swidth; + int sheight; + String str = "GraphZoomScrollPane Demo"; + + public void paint(Graphics g) { + Dimension d = vv.getSize(); + if(font == null) { + font = new Font(g.getFont().getName(), Font.BOLD, 30); + metrics = g.getFontMetrics(font); + swidth = metrics.stringWidth(str); + sheight = metrics.getMaxAscent()+metrics.getMaxDescent(); + x = (d.width-swidth)/2; + y = (int)(d.height-sheight*1.5); + } + g.setFont(font); + Color oldColor = g.getColor(); + g.setColor(Color.lightGray); + g.drawString(str, x, y); + g.setColor(oldColor); + } + public boolean useTransform() { + return false; + } + }); + + vv.addGraphMouseListener(new TestGraphMouseListener()); + vv.getRenderer().setVertexRenderer( + new GradientVertexRenderer( + Color.white, Color.red, + Color.white, Color.blue, + vv.getPickedVertexState(), + false)); + vv.getRenderContext().setEdgeDrawPaintTransformer(Functions.constant(Color.lightGray)); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + vv.getRenderContext().setArrowDrawPaintTransformer(Functions.constant(Color.lightGray)); + + // add my listeners for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.setEdgeToolTipTransformer(new Function() { + public String apply(Number edge) { + return "E"+graph.getEndpoints(edge).toString(); + }}); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner()); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO); + vv.setForeground(Color.lightGray); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + vv.addKeyListener(graphMouse.getModeKeyListener()); + vv.setToolTipText("

    Type 'p' for Pick mode

    Type 't' for Transform mode"); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton reset = new JButton("reset"); + reset.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity(); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity(); + }}); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + controls.add(reset); + content.add(controls, BorderLayout.SOUTH); + + frame.pack(); + frame.setVisible(true); + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private String[] createVertices(int count) { + String[] v = new String[count]; + for (int i = 0; i < count; i++) { + v[i] = "V"+i; + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(String[] v) { + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[3], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED); + } + + /** + * A nested class to demo the GraphMouseListener finding the + * right vertices after zoom/pan + */ + static class TestGraphMouseListener implements GraphMouseListener { + + public void graphClicked(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was clicked at ("+me.getX()+","+me.getY()+")"); + } + public void graphPressed(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was pressed at ("+me.getX()+","+me.getY()+")"); + } + public void graphReleased(V v, MouseEvent me) { + System.err.println("Vertex "+v+" was released at ("+me.getX()+","+me.getY()+")"); + } + } + + public static void main(String[] args) + { + new GraphZoomScrollPaneDemo(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ImageEdgeLabelDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ImageEdgeLabelDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ImageEdgeLabelDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ImageEdgeLabelDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.URL; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; + +/** + * Demonstrates the use of images on graph edge labels. + * + * @author Tom Nelson + * + */ +public class ImageEdgeLabelDemo extends JApplet { + + /** + * + */ + private static final long serialVersionUID = -4332663871914930864L; + + private static final int VERTEX_COUNT=11; + + /** + * the graph + */ + DirectedGraph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + public ImageEdgeLabelDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseMultigraph(); + createGraph(VERTEX_COUNT); + + FRLayout layout = new FRLayout(graph); + layout.setMaxIterations(100); + vv = new VisualizationViewer(layout, new Dimension(400,400)); + + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + + vv.setBackground(Color.white); + + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelTransformer(new Function() { + URL url = getClass().getResource("/images/lightning-s.gif"); + public String apply(Number input) { + return ""; + }}); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.setEdgeToolTipTransformer(new ToStringLabeller()); + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(scaleGrid); + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private void createGraph(int vertexCount) { + for (int i = 0; i < vertexCount; i++) { + graph.addVertex(i); + } + int j=0; + graph.addEdge(j++, 0, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 3, 0, EdgeType.DIRECTED); + graph.addEdge(j++, 0, 4, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 5, 3, EdgeType.DIRECTED); + graph.addEdge(j++, 2, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 8, 2, EdgeType.DIRECTED); + graph.addEdge(j++, 3, 8, EdgeType.DIRECTED); + graph.addEdge(j++, 6, 7, EdgeType.DIRECTED); + graph.addEdge(j++, 7, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 0, 9, EdgeType.DIRECTED); + graph.addEdge(j++, 9, 8, EdgeType.DIRECTED); + graph.addEdge(j++, 7, 6, EdgeType.DIRECTED); + graph.addEdge(j++, 6, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 2, EdgeType.DIRECTED); + graph.addEdge(j++, 5, 4, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 10, EdgeType.DIRECTED); + graph.addEdge(j++, 10, 4, EdgeType.DIRECTED); + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new ImageEdgeLabelDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/InternalFrameSatelliteViewDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/InternalFrameSatelliteViewDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/InternalFrameSatelliteViewDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/InternalFrameSatelliteViewDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.ISOMLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.SatelliteVisualizationViewer; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; + +/** + * Similar to the SatelliteViewDemo, but using JInternalFrame. + * + * @author Tom Nelson + * + */ +public class InternalFrameSatelliteViewDemo { + + static final String instructions = + ""+ + "

    Instructions for Mouse Listeners

    "+ + "

    There are two modes, Transforming and Picking."+ + "

    The modes are selected with a toggle button."+ + + "

    Transforming Mode:"+ + "

      "+ + "
    • Mouse1+drag pans the graph"+ + "
    • Mouse1+Shift+drag rotates the graph"+ + "
    • Mouse1+CTRL(or Command)+drag shears the graph"+ + "
    "+ + + "Picking Mode:"+ + "
      "+ + "
    • Mouse1 on a Vertex selects the vertex"+ + "
    • Mouse1 elsewhere unselects all Vertices"+ + "
    • Mouse1+Shift on a Vertex adds/removes Vertex selection"+ + "
    • Mouse1+drag on a Vertex moves all selected Vertices"+ + "
    • Mouse1+drag elsewhere selects Vertices in a region"+ + "
    • Mouse1+Shift+drag adds selection of Vertices in a new region"+ + "
    • Mouse1+CTRL on a Vertex selects the vertex and centers the display on it"+ + "
    "+ + "Both Modes:"+ + "
      "+ + "
    • Mousewheel scales the layout > 1 and scales the view < 1"; + + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + VisualizationViewer satellite; + + JInternalFrame dialog; + + JDesktopPane desktop; + + /** + * create an instance of a simple graph with controls to + * demo the zoom features. + * + */ + public InternalFrameSatelliteViewDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + Layout layout = new ISOMLayout(graph); + + vv = new VisualizationViewer(layout, new Dimension(600,600)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.red, Color.yellow)); + + // add my listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + satellite = + new SatelliteVisualizationViewer(vv, new Dimension(200,200)); + satellite.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(satellite.getPickedEdgeState(), Color.black, Color.cyan)); + satellite.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(satellite.getPickedVertexState(), Color.red, Color.yellow)); + + ScalingControl satelliteScaler = new CrossoverScalingControl(); + satellite.scaleToLayout(satelliteScaler); + + JFrame frame = new JFrame(); + desktop = new JDesktopPane(); + Container content = frame.getContentPane(); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(desktop); + content.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JInternalFrame vvFrame = new JInternalFrame(); + vvFrame.getContentPane().add(vv); + vvFrame.pack(); + vvFrame.setVisible(true); //necessary as of 1.3 + desktop.add(vvFrame); + try { + vvFrame.setSelected(true); + } catch (java.beans.PropertyVetoException e) {} + + dialog = new JInternalFrame(); + desktop.add(dialog); + content = dialog.getContentPane(); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + JButton dismiss = new JButton("Dismiss"); + dismiss.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e) { + dialog.setVisible(false); + } + }); + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showInternalMessageDialog(dialog, instructions, + "Instructions", JOptionPane.PLAIN_MESSAGE); + } + }); + JPanel controls = new JPanel(new GridLayout(2,2)); + controls.add(plus); + controls.add(minus); + controls.add(dismiss); + controls.add(help); + content.add(satellite); + content.add(controls, BorderLayout.SOUTH); + + JButton zoomer = new JButton("Show Satellite View"); + zoomer.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dialog.pack(); + dialog.setLocation(desktop.getWidth()-dialog.getWidth(),0); + dialog.show(); + try { + dialog.setSelected(true); + } catch (java.beans.PropertyVetoException ex) {} + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(((ModalGraphMouse)satellite.getGraphMouse()).getModeListener()); + JPanel p = new JPanel(); + p.add(zoomer); + p.add(modeBox); + + frame.getContentPane().add(p, BorderLayout.SOUTH); + frame.setSize(800, 800); + frame.setVisible(true); + } + + public static void main(String[] args) { + new InternalFrameSatelliteViewDemo(); + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/L2RTreeLayoutDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/L2RTreeLayoutDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/L2RTreeLayoutDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/L2RTreeLayoutDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToggleButton; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.util.Animator; + +/** + * A variant of TreeLayoutDemo that rotates the view by 90 degrees from the + * default orientation. + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class L2RTreeLayoutDemo extends JApplet { + + /** + * the graph + */ + Forest graph; + + Supplier> graphFactory = + new Supplier>() { + + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + + Supplier> treeFactory = + new Supplier> () { + + public Tree get() { + return new DelegateTree(graphFactory); + } + }; + + Supplier edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + + Supplier vertexFactory = new Supplier() { + int i=0; + public String get() { + return "V"+i++; + }}; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + VisualizationServer.Paintable rings; + + String root; + + TreeLayout treeLayout; + + RadialTreeLayout radialLayout; + + public L2RTreeLayoutDemo() { + + // create a simple graph for the demo + graph = new DelegateForest(); + + createTree(); + + treeLayout = new TreeLayout(graph); + radialLayout = new RadialTreeLayout(graph); + radialLayout.setSize(new Dimension(600,600)); + vv = new VisualizationViewer(treeLayout, new Dimension(600,600)); + vv.setBackground(Color.white); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph)); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + rings = new Rings(); + + setLtoR(vv); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JToggleButton radial = new JToggleButton("Radial"); + radial.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + + LayoutTransition lt = + new LayoutTransition(vv, treeLayout, radialLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.addPreRenderPaintable(rings); + } else { + LayoutTransition lt = + new LayoutTransition(vv, radialLayout, treeLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + setLtoR(vv); + vv.removePreRenderPaintable(rings); + } + + vv.repaint(); + }}); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(radial); + controls.add(scaleGrid); + controls.add(modeBox); + + content.add(controls, BorderLayout.SOUTH); + } + + private void setLtoR(VisualizationViewer vv) { + Layout layout = vv.getModel().getGraphLayout(); + Dimension d = layout.getSize(); + Point2D center = new Point2D.Double(d.width/2, d.height/2); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).rotate(-Math.PI/2, center); + } + + class Rings implements VisualizationServer.Paintable { + + Collection depths; + + public Rings() { + depths = getDepths(); + } + + private Collection getDepths() { + Set depths = new HashSet(); + Map polarLocations = radialLayout.getPolarLocations(); + for(String v : graph.getVertices()) { + PolarPoint pp = polarLocations.get(v); + depths.add(pp.getRadius()); + } + return depths; + } + + public void paint(Graphics g) { + g.setColor(Color.lightGray); + + Graphics2D g2d = (Graphics2D)g; + Point2D center = radialLayout.getCenter(); + + Ellipse2D ellipse = new Ellipse2D.Double(); + for(double d : depths) { + ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, + center.getX()+d, center.getY()+d); + Shape shape = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse); + g2d.draw(shape); + } + } + + public boolean useTransform() { + return true; + } + } + + /** + * + */ + private void createTree() { + graph.addVertex("V0"); + graph.addEdge(edgeFactory.get(), "V0", "V1"); + graph.addEdge(edgeFactory.get(), "V0", "V2"); + graph.addEdge(edgeFactory.get(), "V1", "V4"); + graph.addEdge(edgeFactory.get(), "V2", "V3"); + graph.addEdge(edgeFactory.get(), "V2", "V5"); + graph.addEdge(edgeFactory.get(), "V4", "V6"); + graph.addEdge(edgeFactory.get(), "V4", "V7"); + graph.addEdge(edgeFactory.get(), "V3", "V8"); + graph.addEdge(edgeFactory.get(), "V6", "V9"); + graph.addEdge(edgeFactory.get(), "V4", "V10"); + + graph.addVertex("A0"); + graph.addEdge(edgeFactory.get(), "A0", "A1"); + graph.addEdge(edgeFactory.get(), "A0", "A2"); + graph.addEdge(edgeFactory.get(), "A0", "A3"); + + graph.addVertex("B0"); + graph.addEdge(edgeFactory.get(), "B0", "B1"); + graph.addEdge(edgeFactory.get(), "B0", "B2"); + graph.addEdge(edgeFactory.get(), "B1", "B4"); + graph.addEdge(edgeFactory.get(), "B2", "B3"); + graph.addEdge(edgeFactory.get(), "B2", "B5"); + graph.addEdge(edgeFactory.get(), "B4", "B6"); + graph.addEdge(edgeFactory.get(), "B4", "B7"); + graph.addEdge(edgeFactory.get(), "B3", "B8"); + graph.addEdge(edgeFactory.get(), "B6", "B9"); + + } + + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new L2RTreeLayoutDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/LensDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/LensDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/LensDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/LensDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenuBar; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.plaf.basic.BasicLabelUI; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseGraph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.LensMagnificationGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer; +import edu.uci.ics.jung.visualization.transform.LayoutLensSupport; +import edu.uci.ics.jung.visualization.transform.LensSupport; +import edu.uci.ics.jung.visualization.transform.MagnifyTransformer; +import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer; +import edu.uci.ics.jung.visualization.transform.shape.MagnifyShapeTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport; + +/** + * Demonstrates the use of HyperbolicTransform + * and MagnifyTransform + * applied to either the model (graph layout) or the view + * (VisualizationViewer) + * The hyperbolic transform is applied in an elliptical lens + * that affects that part of the visualization. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class LensDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + + FRLayout graphLayout; + + /** + * a grid shaped graph + */ + Graph grid; + + Layout gridLayout; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * provides a Hyperbolic lens for the view + */ + LensSupport hyperbolicViewSupport; + /** + * provides a magnification lens for the view + */ + LensSupport magnifyViewSupport; + + /** + * provides a Hyperbolic lens for the model + */ + LensSupport hyperbolicLayoutSupport; + /** + * provides a magnification lens for the model + */ + LensSupport magnifyLayoutSupport; + + ScalingControl scaler; + + /** + * create an instance of a simple graph with controls to + * demo the zoomand hyperbolic features. + * + */ + public LensDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + graphLayout = new FRLayout(graph); + graphLayout.setMaxIterations(1000); + + Dimension preferredSize = new Dimension(600,600); + Map map = new HashMap(); + Function vlf = + Functions.forMap(map); + grid = this.generateVertexGrid(map, preferredSize, 25); + gridLayout = new StaticLayout(grid, vlf, preferredSize); + + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(graphLayout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + PickedState ps = vv.getPickedVertexState(); + PickedState pes = vv.getPickedEdgeState(); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(ps, Color.red, Color.yellow)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.cyan)); + vv.setBackground(Color.white); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + + final Function ovals = vv.getRenderContext().getVertexShapeTransformer(); + final Function squares = + Functions.constant(new Rectangle2D.Float(-10,-10,20,20)); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + /** + * the regular graph mouse for the normal view + */ + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + hyperbolicViewSupport = + new ViewLensSupport(vv, new HyperbolicShapeTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), + new ModalLensGraphMouse()); + hyperbolicLayoutSupport = + new LayoutLensSupport(vv, new HyperbolicTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)), + new ModalLensGraphMouse()); + magnifyViewSupport = + new ViewLensSupport(vv, new MagnifyShapeTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), + new ModalLensGraphMouse(new LensMagnificationGraphMousePlugin(1.f, 6.f, .2f))); + magnifyLayoutSupport = + new LayoutLensSupport(vv, new MagnifyTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)), + new ModalLensGraphMouse(new LensMagnificationGraphMousePlugin(1.f, 6.f, .2f))); + hyperbolicLayoutSupport.getLensTransformer().setLensShape(hyperbolicViewSupport.getLensTransformer().getLensShape()); + magnifyViewSupport.getLensTransformer().setLensShape(hyperbolicLayoutSupport.getLensTransformer().getLensShape()); + magnifyLayoutSupport.getLensTransformer().setLensShape(magnifyViewSupport.getLensTransformer().getLensShape()); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + ButtonGroup radio = new ButtonGroup(); + JRadioButton normal = new JRadioButton("None"); + normal.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + if(hyperbolicViewSupport != null) { + hyperbolicViewSupport.deactivate(); + } + if(hyperbolicLayoutSupport != null) { + hyperbolicLayoutSupport.deactivate(); + } + if(magnifyViewSupport != null) { + magnifyViewSupport.deactivate(); + } + if(magnifyLayoutSupport != null) { + magnifyLayoutSupport.deactivate(); + } + } + } + }); + + final JRadioButton hyperView = new JRadioButton("Hyperbolic View"); + hyperView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + final JRadioButton hyperModel = new JRadioButton("Hyperbolic Layout"); + hyperModel.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + hyperbolicLayoutSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + final JRadioButton magnifyView = new JRadioButton("Magnified View"); + magnifyView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + magnifyViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + final JRadioButton magnifyModel = new JRadioButton("Magnified Layout"); + magnifyModel.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + magnifyLayoutSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + JLabel modeLabel = new JLabel(" Mode Menu >>"); + modeLabel.setUI(new VerticalLabelUI(false)); + radio.add(normal); + radio.add(hyperModel); + radio.add(hyperView); + radio.add(magnifyModel); + radio.add(magnifyView); + normal.setSelected(true); + + graphMouse.addItemListener(hyperbolicLayoutSupport.getGraphMouse().getModeListener()); + graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener()); + graphMouse.addItemListener(magnifyLayoutSupport.getGraphMouse().getModeListener()); + graphMouse.addItemListener(magnifyViewSupport.getGraphMouse().getModeListener()); + + ButtonGroup graphRadio = new ButtonGroup(); + JRadioButton graphButton = new JRadioButton("Graph"); + graphButton.setSelected(true); + graphButton.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + visualizationModel.setGraphLayout(graphLayout); + vv.getRenderContext().setVertexShapeTransformer(ovals); + vv.getRenderContext().setVertexLabelTransformer( + new ToStringLabeller()); + vv.repaint(); + } + }}); + JRadioButton gridButton = new JRadioButton("Grid"); + gridButton.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + visualizationModel.setGraphLayout(gridLayout); + vv.getRenderContext().setVertexShapeTransformer(squares); + vv.getRenderContext().setVertexLabelTransformer(Functions.constant(null)); + vv.repaint(); + } + }}); + graphRadio.add(graphButton); + graphRadio.add(gridButton); + + JPanel modePanel = new JPanel(new GridLayout(3,1)); + modePanel.setBorder(BorderFactory.createTitledBorder("Display")); + modePanel.add(graphButton); + modePanel.add(gridButton); + + JMenuBar menubar = new JMenuBar(); + menubar.add(graphMouse.getModeMenu()); + gzsp.setCorner(menubar); + + + Box controls = Box.createHorizontalBox(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel hyperControls = new JPanel(new GridLayout(3,2)); + hyperControls.setBorder(BorderFactory.createTitledBorder("Examiner Lens")); + zoomControls.add(plus); + zoomControls.add(minus); + + hyperControls.add(normal); + hyperControls.add(new JLabel()); + + hyperControls.add(hyperModel); + hyperControls.add(magnifyModel); + + hyperControls.add(hyperView); + hyperControls.add(magnifyView); + + controls.add(zoomControls); + controls.add(hyperControls); + controls.add(modePanel); + controls.add(modeLabel); + content.add(controls, BorderLayout.SOUTH); + } + + private Graph generateVertexGrid(Map vlf, + Dimension d, int interval) { + int count = d.width/interval * d.height/interval; + Graph graph = new SparseGraph(); + for(int i=0; i graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * some icon names to use + */ + String[] iconNames = { + "apple", + "os", + "x", + "linux", + "inputdevices", + "wireless", + "graphics3", + "gamespcgames", + "humor", + "music", + "privacy" + }; + + LensSupport viewSupport; + LensSupport modelSupport; + LensSupport magnifyLayoutSupport; + LensSupport magnifyViewSupport; + /** + * create an instance of a simple graph with controls to + * demo the zoom features. + * + */ + public LensVertexImageShaperDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + Number[] vertices = createVertices(11); + + // a Map for the labels + Map map = new HashMap(); + for(int i=0; i iconMap = new HashMap(); + for(int i=0; i layout = new FRLayout(graph); + layout.setMaxIterations(100); + vv = new VisualizationViewer(layout, new Dimension(600,600)); + + Function vpf = + new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.white, Color.yellow); + vv.getRenderContext().setVertexFillPaintTransformer(vpf); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + + vv.setBackground(Color.white); + + final Function vertexStringerImpl = + new VertexStringerImpl(map); + vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); + + + // features on and off. For a real application, use VertexIconAndShapeFunction instead. + final VertexIconShapeTransformer vertexImageShapeFunction = + new VertexIconShapeTransformer(new EllipseVertexShapeTransformer()); + + final Function vertexIconFunction = Functions.forMap(iconMap); + + vertexImageShapeFunction.setIconMap(iconMap); + + vv.getRenderContext().setVertexShapeTransformer(vertexImageShapeFunction); + vv.getRenderContext().setVertexIconTransformer(vertexIconFunction); + + + // Get the pickedState and add a listener that will decorate the + // Vertex images with a checkmark icon when they are picked + PickedState ps = vv.getPickedVertexState(); + ps.addItemListener(new PickWithIconListener(vertexIconFunction)); + + vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){ + int x; + int y; + Font font; + FontMetrics metrics; + int swidth; + int sheight; + String str = "Thank You, slashdot.org, for the images!"; + + public void paint(Graphics g) { + Dimension d = vv.getSize(); + if(font == null) { + font = new Font(g.getFont().getName(), Font.BOLD, 20); + metrics = g.getFontMetrics(font); + swidth = metrics.stringWidth(str); + sheight = metrics.getMaxAscent()+metrics.getMaxDescent(); + x = (d.width-swidth)/2; + y = (int)(d.height-sheight*1.5); + } + g.setFont(font); + Color oldColor = g.getColor(); + g.setColor(Color.lightGray); + g.drawString(str, x, y); + g.setColor(oldColor); + } + public boolean useTransform() { + return false; + } + }); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(scaleGrid); + + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + + this.viewSupport = new MagnifyImageLensSupport(vv); +// new ViewLensSupport(vv, new HyperbolicShapeTransformer(vv, +// vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), +// new ModalLensGraphMouse()); + + this.modelSupport = new LayoutLensSupport(vv); + + graphMouse.addItemListener(modelSupport.getGraphMouse().getModeListener()); + graphMouse.addItemListener(viewSupport.getGraphMouse().getModeListener()); + + ButtonGroup radio = new ButtonGroup(); + JRadioButton none = new JRadioButton("None"); + none.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + if(viewSupport != null) { + viewSupport.deactivate(); + } + if(modelSupport != null) { + modelSupport.deactivate(); + } + } + }); + none.setSelected(true); + + JRadioButton hyperView = new JRadioButton("View"); + hyperView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + viewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + + JRadioButton hyperModel = new JRadioButton("Layout"); + hyperModel.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + modelSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + radio.add(none); + radio.add(hyperView); + radio.add(hyperModel); + + JMenuBar menubar = new JMenuBar(); + JMenu modeMenu = graphMouse.getModeMenu(); + menubar.add(modeMenu); + + JPanel lensPanel = new JPanel(new GridLayout(2,0)); + lensPanel.setBorder(BorderFactory.createTitledBorder("Lens")); + lensPanel.add(none); + lensPanel.add(hyperView); + lensPanel.add(hyperModel); + controls.add(lensPanel); + } + + /** + * A simple implementation of VertexStringer that + * gets Vertex labels from a Map + * + * @author Tom Nelson + * + * + */ + class VertexStringerImpl implements Function { + + Map map = new HashMap(); + + boolean enabled = true; + + public VertexStringerImpl(Map map) { + this.map = map; + } + + /** + * @see edu.uci.ics.jung.graph.decorators.VertexStringer#getLabel(edu.uci.ics.jung.graph.Vertex) + */ + public String apply(V v) { + if(isEnabled()) { + return map.get(v); + } else { + return ""; + } + } + + /** + * @return Returns the enabled. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * @param enabled The enabled to set. + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private Number[] createVertices(int count) { + Number[] v = new Number[count]; + for (int i = 0; i < count; i++) { + v[i] = new Integer(i); + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(Number[] v) { + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[0], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[5], v[3], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[2], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[10], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[10], v[4], EdgeType.DIRECTED); + } + + public static class PickWithIconListener implements ItemListener { + Function imager; + Icon checked; + + public PickWithIconListener(Function imager) { + this.imager = imager; + checked = new Checkmark(Color.red); + } + + public void itemStateChanged(ItemEvent e) { + Icon icon = imager.apply((Number)e.getItem()); + if(icon != null && icon instanceof LayeredIcon) { + if(e.getStateChange() == ItemEvent.SELECTED) { + ((LayeredIcon)icon).add(checked); + } else { + ((LayeredIcon)icon).remove(checked); + } + } + } + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new LensVertexImageShaperDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/MinimumSpanningTreeDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/MinimumSpanningTreeDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/MinimumSpanningTreeDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/MinimumSpanningTreeDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.algorithms.shortestpath.MinimumSpanningForest2; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.MultiPickedState; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Demonstrates a single graph with 3 layouts in 3 views. + * The first view is an undirected graph using KKLayout + * The second view show a TreeLayout view of a MinimumSpanningTree + * of the first graph. The third view shows the complete graph + * of the first view, using the layout positions of the + * MinimumSpanningTree tree view. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class MinimumSpanningTreeDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + Forest tree; + + /** + * the visual components and renderers for the graph + */ + VisualizationViewer vv0; + VisualizationViewer vv1; + VisualizationViewer vv2; + + /** + * the normal Function + */ + MutableTransformer layoutTransformer; + + Dimension preferredSize = new Dimension(300,300); + Dimension preferredLayoutSize = new Dimension(400,400); + Dimension preferredSizeRect = new Dimension(500,250); + + /** + * create an instance of a simple graph in two views with controls to + * demo the zoom features. + * + */ + public MinimumSpanningTreeDemo() { + + // create a simple graph for the demo + // both models will share one graph + graph = + TestGraphs.getDemoGraph(); + + MinimumSpanningForest2 prim = + new MinimumSpanningForest2(graph, + new DelegateForest(), DelegateTree.getFactory(), + Functions.constant(1.0)); + + tree = prim.getForest(); + + // create two layouts for the one graph, one layout for each model + Layout layout0 = new KKLayout(graph); + layout0.setSize(preferredLayoutSize); + Layout layout1 = new TreeLayout(tree); + Layout layout2 = new StaticLayout(graph, layout1); + + // create the two models, each with a different layout + VisualizationModel vm0 = + new DefaultVisualizationModel(layout0, preferredSize); + VisualizationModel vm1 = + new DefaultVisualizationModel(layout1, preferredSizeRect); + VisualizationModel vm2 = + new DefaultVisualizationModel(layout2, preferredSizeRect); + + // create the two views, one for each model + // they share the same renderer + vv0 = new VisualizationViewer(vm0, preferredSize); + vv1 = new VisualizationViewer(vm1, preferredSizeRect); + vv2 = new VisualizationViewer(vm2, preferredSizeRect); + + vv1.getRenderContext().setMultiLayerTransformer(vv0.getRenderContext().getMultiLayerTransformer()); + vv2.getRenderContext().setMultiLayerTransformer(vv0.getRenderContext().getMultiLayerTransformer()); + + vv1.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + + vv0.addChangeListener(vv1); + vv1.addChangeListener(vv2); + + vv0.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv2.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + + Color back = Color.decode("0xffffbb"); + vv0.setBackground(back); + vv1.setBackground(back); + vv2.setBackground(back); + + vv0.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + vv0.setForeground(Color.darkGray); + vv1.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + vv1.setForeground(Color.darkGray); + vv2.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + vv2.setForeground(Color.darkGray); + + // share one PickedState between the two views + PickedState ps = new MultiPickedState(); + vv0.setPickedVertexState(ps); + vv1.setPickedVertexState(ps); + vv2.setPickedVertexState(ps); + + PickedState pes = new MultiPickedState(); + vv0.setPickedEdgeState(pes); + vv1.setPickedEdgeState(pes); + vv2.setPickedEdgeState(pes); + + + // set an edge paint function that will show picking for edges + vv0.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv0.getPickedEdgeState(), Color.black, Color.red)); + vv0.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv0.getPickedVertexState(), + Color.red, Color.yellow)); + vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv1.getPickedEdgeState(), Color.black, Color.red)); + vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv1.getPickedVertexState(), + Color.red, Color.yellow)); + + // add default listeners for ToolTips + vv0.setVertexToolTipTransformer(new ToStringLabeller()); + vv1.setVertexToolTipTransformer(new ToStringLabeller()); + vv2.setVertexToolTipTransformer(new ToStringLabeller()); + + vv0.setLayout(new BorderLayout()); + vv1.setLayout(new BorderLayout()); + vv2.setLayout(new BorderLayout()); + + Font font = vv0.getFont().deriveFont(Font.BOLD, 16); + JLabel vv0Label = new JLabel("Original Graph

      using KKLayout"); + vv0Label.setFont(font); + JLabel vv1Label = new JLabel("Minimum Spanning Trees"); + vv1Label.setFont(font); + JLabel vv2Label = new JLabel("Original Graph using TreeLayout"); + vv2Label.setFont(font); + JPanel flow0 = new JPanel(); + flow0.setOpaque(false); + JPanel flow1 = new JPanel(); + flow1.setOpaque(false); + JPanel flow2 = new JPanel(); + flow2.setOpaque(false); + flow0.add(vv0Label); + flow1.add(vv1Label); + flow2.add(vv2Label); + vv0.add(flow0, BorderLayout.NORTH); + vv1.add(flow1, BorderLayout.NORTH); + vv2.add(flow2, BorderLayout.NORTH); + + Container content = getContentPane(); + JPanel grid = new JPanel(new GridLayout(0,1)); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(new GraphZoomScrollPane(vv0), BorderLayout.WEST); + grid.add(new GraphZoomScrollPane(vv1)); + grid.add(new GraphZoomScrollPane(vv2)); + panel.add(grid); + + content.add(panel); + + // create a GraphMouse for each view + DefaultModalGraphMouse gm0 = new DefaultModalGraphMouse(); + DefaultModalGraphMouse gm1 = new DefaultModalGraphMouse(); + DefaultModalGraphMouse gm2 = new DefaultModalGraphMouse(); + + vv0.setGraphMouse(gm0); + vv1.setGraphMouse(gm1); + vv2.setGraphMouse(gm2); + + // create zoom buttons for scaling the Function that is + // shared between the two models. + final ScalingControl scaler = new CrossoverScalingControl(); + + vv0.scaleToLayout(scaler); + vv1.scaleToLayout(scaler); + vv2.scaleToLayout(scaler); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1.1f, vv1.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1/1.1f, vv1.getCenter()); + } + }); + + JPanel zoomPanel = new JPanel(new GridLayout(1,2)); + zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + gm1.getModeComboBox().addItemListener(gm2.getModeListener()); + gm1.getModeComboBox().addItemListener(gm0.getModeListener()); + modePanel.add(gm1.getModeComboBox()); + + JPanel controls = new JPanel(); + zoomPanel.add(plus); + zoomPanel.add(minus); + controls.add(zoomPanel); + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new MinimumSpanningTreeDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/MultiViewDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/MultiViewDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/MultiViewDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/MultiViewDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.geom.Rectangle2D; + +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.AnimatedPickingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.LayoutScalingControl; +import edu.uci.ics.jung.visualization.control.PickingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.RotatingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ScalingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ShearingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.TranslatingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ViewScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.MultiPickedState; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.picking.ShapePickSupport; + +/** + * Demonstrates 3 views of one graph in one model with one layout. + * Each view uses a different scaling graph mouse. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class MultiViewDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + + /** + * the visual components and renderers for the graph + */ + VisualizationViewer vv1; + VisualizationViewer vv2; + VisualizationViewer vv3; + + /** + * the normal Function + */ +// MutableTransformer Function; + + Dimension preferredSize = new Dimension(300,300); + + final String messageOne = "The mouse wheel will scale the model's layout when activated"+ + " in View 1. Since all three views share the same layout Function, all three views will"+ + " show the same scaling of the layout."; + + final String messageTwo = "The mouse wheel will scale the view when activated in"+ + " View 2. Since all three views share the same view Function, all three views will be affected."; + + final String messageThree = " The mouse wheel uses a 'crossover' feature in View 3."+ + " When the combined layout and view scale is greater than '1', the model's layout will be scaled."+ + " Since all three views share the same layout Function, all three views will show the same "+ + " scaling of the layout.\n When the combined scale is less than '1', the scaling function"+ + " crosses over to the view, and then, since all three views share the same view Function,"+ + " all three views will show the same scaling."; + + JTextArea textArea; + JScrollPane scrollPane; + + /** + * create an instance of a simple graph in two views with controls to + * demo the zoom features. + * + */ + public MultiViewDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + // create one layout for the graph + FRLayout layout = new FRLayout(graph); + layout.setMaxIterations(1000); + + // create one model that all 3 views will share + VisualizationModel visualizationModel = + new DefaultVisualizationModel(layout, preferredSize); + + // create 3 views that share the same model + vv1 = new VisualizationViewer(visualizationModel, preferredSize); + vv2 = new VisualizationViewer(visualizationModel, preferredSize); + vv3 = new VisualizationViewer(visualizationModel, preferredSize); + + vv1.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + vv2.getRenderContext().setVertexShapeTransformer( + Functions.constant(new Rectangle2D.Float(-6,-6,12,12))); + + vv2.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph)); + + vv3.getRenderContext().setEdgeShapeTransformer(EdgeShape.cubicCurve(graph)); + +// Function = vv1.getLayoutTransformer(); +// vv2.setLayoutTransformer(Function); +// vv3.setLayoutTransformer(Function); +// +// vv2.setViewTransformer(vv1.getViewTransformer()); +// vv3.setViewTransformer(vv1.getViewTransformer()); + + vv2.getRenderContext().setMultiLayerTransformer(vv1.getRenderContext().getMultiLayerTransformer()); + vv3.getRenderContext().setMultiLayerTransformer(vv1.getRenderContext().getMultiLayerTransformer()); + + vv1.getRenderContext().getMultiLayerTransformer().addChangeListener(vv1); + vv2.getRenderContext().getMultiLayerTransformer().addChangeListener(vv2); + vv3.getRenderContext().getMultiLayerTransformer().addChangeListener(vv3); + + + vv1.setBackground(Color.white); + vv2.setBackground(Color.white); + vv3.setBackground(Color.white); + + // create one pick support for all 3 views to share + GraphElementAccessor pickSupport = new ShapePickSupport(vv1); + vv1.setPickSupport(pickSupport); + vv2.setPickSupport(pickSupport); + vv3.setPickSupport(pickSupport); + + // create one picked state for all 3 views to share + PickedState pes = new MultiPickedState(); + PickedState pvs = new MultiPickedState(); + vv1.setPickedVertexState(pvs); + vv2.setPickedVertexState(pvs); + vv3.setPickedVertexState(pvs); + vv1.setPickedEdgeState(pes); + vv2.setPickedEdgeState(pes); + vv3.setPickedEdgeState(pes); + + // set an edge paint function that shows picked edges + vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.red)); + vv2.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.red)); + vv3.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.red)); + vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(pvs, Color.red, Color.yellow)); + vv2.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(pvs, Color.blue, Color.cyan)); + vv3.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(pvs, Color.red, Color.yellow)); + + // add default listener for ToolTips + vv1.setVertexToolTipTransformer(new ToStringLabeller()); + vv2.setVertexToolTipTransformer(new ToStringLabeller()); + vv3.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + JPanel panel = new JPanel(new GridLayout(1,0)); + + final JPanel p1 = new JPanel(new BorderLayout()); + final JPanel p2 = new JPanel(new BorderLayout()); + final JPanel p3 = new JPanel(new BorderLayout()); + + p1.add(new GraphZoomScrollPane(vv1)); + p2.add(new GraphZoomScrollPane(vv2)); + p3.add(new GraphZoomScrollPane(vv3)); + + JButton h1 = new JButton("?"); + h1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textArea.setText(messageOne); + JOptionPane.showMessageDialog(p1, scrollPane, + "View 1", JOptionPane.PLAIN_MESSAGE); + }}); + JButton h2 = new JButton("?"); + h2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textArea.setText(messageTwo); + JOptionPane.showMessageDialog(p2, scrollPane, + "View 2", JOptionPane.PLAIN_MESSAGE); + }}); + JButton h3 = new JButton("?"); + h3.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textArea.setText(messageThree); + textArea.setCaretPosition(0); + JOptionPane.showMessageDialog(p3, scrollPane, + "View 3", JOptionPane.PLAIN_MESSAGE); + }}); + + // create a GraphMouse for each view + // each one has a different scaling plugin + DefaultModalGraphMouse gm1 = new DefaultModalGraphMouse() { + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new ScalingGraphMousePlugin(new LayoutScalingControl(), 0); + rotatingPlugin = new RotatingGraphMousePlugin(); + shearingPlugin = new ShearingGraphMousePlugin(); + + add(scalingPlugin); + setMode(Mode.TRANSFORMING); + } + }; + + DefaultModalGraphMouse gm2 = new DefaultModalGraphMouse() { + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new ScalingGraphMousePlugin(new ViewScalingControl(), 0); + rotatingPlugin = new RotatingGraphMousePlugin(); + shearingPlugin = new ShearingGraphMousePlugin(); + + add(scalingPlugin); + setMode(Mode.TRANSFORMING); + } + + }; + + DefaultModalGraphMouse gm3 = new DefaultModalGraphMouse() {}; + + vv1.setGraphMouse(gm1); + vv2.setGraphMouse(gm2); + vv3.setGraphMouse(gm3); + + vv1.setToolTipText("

      MouseWheel Scales Layout
      "); + vv2.setToolTipText("
      MouseWheel Scales View
      "); + vv3.setToolTipText("
      MouseWheel Scales Layout and

      crosses over to view

      ctrl+MouseWheel scales view

      "); + + vv1.addPostRenderPaintable(new BannerLabel(vv1, "View 1")); + vv2.addPostRenderPaintable(new BannerLabel(vv2, "View 2")); + vv3.addPostRenderPaintable(new BannerLabel(vv3, "View 3")); + + textArea = new JTextArea(6,30); + scrollPane = new JScrollPane(textArea, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + textArea.setLineWrap(true); + textArea.setWrapStyleWord(true); + textArea.setEditable(false); + + JPanel flow = new JPanel(); + flow.add(h1); + flow.add(gm1.getModeComboBox()); + p1.add(flow, BorderLayout.SOUTH); + flow = new JPanel(); + flow.add(h2); + flow.add(gm2.getModeComboBox()); + p2.add(flow, BorderLayout.SOUTH); + flow = new JPanel(); + flow.add(h3); + flow.add(gm3.getModeComboBox()); + p3.add(flow, BorderLayout.SOUTH); + + panel.add(p1); + panel.add(p2); + panel.add(p3); + content.add(panel); + + + } + + class BannerLabel implements VisualizationViewer.Paintable { + int x; + int y; + Font font; + FontMetrics metrics; + int swidth; + int sheight; + String str; + VisualizationViewer vv; + + public BannerLabel(VisualizationViewer vv, String label) { + this.vv = vv; + this.str = label; + } + + public void paint(Graphics g) { + Dimension d = vv.getSize(); + if(font == null) { + font = new Font(g.getFont().getName(), Font.BOLD, 30); + metrics = g.getFontMetrics(font); + swidth = metrics.stringWidth(str); + sheight = metrics.getMaxAscent()+metrics.getMaxDescent(); + x = (3*d.width/2-swidth)/2; + y = d.height-sheight; + } + g.setFont(font); + Color oldColor = g.getColor(); + g.setColor(Color.gray); + g.drawString(str, x, y); + g.setColor(oldColor); + } + public boolean useTransform() { + return false; + } + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new MultiViewDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/package.html libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/package.html --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ + + + + + + + +

      Sample applications created using JUNG, largely focused on visualization. +Current features demonstrated in the samples include: +

        +
      • visualization of changing graphs +
      • visualization animation +
      • layouts: BalloonLayout, TreeLayout, RadialTreeLayout +
      • clustering, shortest path, minimum spanning tree +
      • sublayouts +
      • label variations: orientation, position +
      • customization of color, shape, stroke +
      • on-the-fly visualization filtering +
      • graph editor +
      • vertex 'collapsing' +
      • multiple models, multiple views with the same model +
      • vertices as Icons +
      • magnifying lens overlay +
      • satellite view +
      + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/PersistentLayoutDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/PersistentLayoutDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/PersistentLayoutDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/PersistentLayoutDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.PersistentLayout; +import edu.uci.ics.jung.visualization.layout.PersistentLayoutImpl; + + +/** + * Demonstrates the use of PersistentLayout + * and PersistentLayoutImpl. + * + * @author Tom Nelson + * + */ +public class PersistentLayoutDemo { + + /** + * the graph + */ + Graph graph = TestGraphs.getOneComponentGraph(); + + /** + * the name of the file where the layout is saved + */ + String fileName; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + PersistentLayout persistentLayout; + + /** + * create an instance of a simple graph with controls to + * demo the persistence and zoom features. + * + * @param fileName where to save/restore the graph positions + */ + public PersistentLayoutDemo(final String fileName) { + this.fileName = fileName; + + // create a simple graph for the demo + persistentLayout = + new PersistentLayoutImpl(new FRLayout(graph)); + + vv = new VisualizationViewer(persistentLayout); + + // add my listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + DefaultModalGraphMouse gm = new DefaultModalGraphMouse(); + vv.setGraphMouse(gm); + final ScalingControl scaler = new CrossoverScalingControl(); + + vv.scaleToLayout(scaler); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + frame.getContentPane().add(new GraphZoomScrollPane(vv)); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + // create a control panel and buttons for demo + // functions + JPanel p = new JPanel(); + + JButton persist = new JButton("Save Layout"); + // saves the graph vertex positions to a file + persist.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + persistentLayout.persist(fileName); + } catch (IOException e1) { + System.err.println("got "+e1); + } + } + }); + p.add(persist); + + JButton restore = new JButton("Restore Layout"); + // restores the graph vertex positions from a file + // if new vertices were added since the last 'persist', + // they will be placed at random locations + restore.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { +// PersistentLayout pl = (PersistentLayout) vv.getGraphLayout(); + try { + persistentLayout.restore(fileName); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + }); + p.add(restore); + p.add(gm.getModeComboBox()); + + frame.getContentPane().add(p, BorderLayout.SOUTH); + frame.pack();//setSize(600, 600); + frame.setVisible(true); + } + + /** + * a driver for this demo + * @param args should hold the filename for the persistence demo + */ + public static void main(String[] args) { + String filename; + if (args.length >= 1) + filename = args[0]; + else + filename = "PersistentLayoutDemo.out"; + new PersistentLayoutDemo(filename); + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/PluggableRendererDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,1198 @@ +/* + * Copyright (c) 2004, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Nov 7, 2004 + */ +package edu.uci.ics.jung.samples; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GradientPaint; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButton; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.random.MixedRandomGraphGenerator; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.scoring.VoltageScorer; +import edu.uci.ics.jung.algorithms.scoring.util.VertexScoreTransformer; +import edu.uci.ics.jung.algorithms.util.SelfLoopEdgePredicate; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.AbstractPopupGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.AbstractVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.GradientEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.NumberFormattingTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.picking.PickedInfo; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.BasicEdgeArrowRenderingSupport; +import edu.uci.ics.jung.visualization.renderers.CachingEdgeRenderer; +import edu.uci.ics.jung.visualization.renderers.CachingVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.CenterEdgeArrowRenderingSupport; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position; + + +/** + * Shows off some of the capabilities of PluggableRenderer. + * This code provides examples of different ways to provide and + * change the various functions that provide property information + * to the renderer. + * + *

      This demo creates a random mixed-mode graph with random edge + * weights using TestGraph.generateMixedRandomGraph. + * It then runs VoltageRanker on this graph, using half + * of the "seed" vertices from the random graph generation as + * voltage sources, and half of them as voltage sinks. + * + *

      What the controls do: + *

        + *
      • Mouse controls: + *
          + *
        • If your mouse has a scroll wheel, scrolling forward zooms out and + * scrolling backward zooms in. + *
        • Left-clicking on a vertex or edge selects it, and unselects all others. + *
        • Middle-clicking on a vertex or edge toggles its selection state. + *
        • Right-clicking on a vertex brings up a pop-up menu that allows you to + * increase or decrease that vertex's transparency. + *
        • Left-clicking on the background allows you to drag the image around. + *
        • Hovering over a vertex tells you what its voltage is; hovering over an + * edge shows its identity; hovering over the background shows an informational + * message. + *
        + *
      • Vertex stuff: + *
          + *
        • "vertex seed coloring": if checked, the seed vertices are colored blue, + * and all other vertices are colored red. Otherwise, all vertices are colored + * a slightly transparent red (except the currently "picked" vertex, which is + * colored transparent purple). + *
        • "vertex selection stroke highlighting": if checked, the picked vertex + * and its neighbors are all drawn with heavy borders. Otherwise, all vertices + * are drawn with light borders. + *
        • "show vertex ranks (voltages)": if checked, each vertex is labeled with its + * calculated 'voltage'. Otherwise, vertices are unlabeled. + *
        • "vertex degree shapes": if checked, vertices are drawn with a polygon with + * number of sides proportional to its degree. Otherwise, vertices are drawn + * as ellipses. + *
        • "vertex voltage size": if checked, vertices are drawn with a size + * proportional to their voltage ranking. Otherwise, all vertices are drawn + * at the same size. + *
        • "vertex degree ratio stretch": if checked, vertices are drawn with an + * aspect ratio (height/width ratio) proportional to the ratio of their indegree to + * their outdegree. Otherwise, vertices are drawn with an aspect ratio of 1. + *
        • "filter vertices of degree < 4": if checked, does not display any vertices + * (or their incident edges) whose degree in the original graph is less than 4; + * otherwise, all vertices are drawn. + *
        + *
      • Edge stuff: + *
          + *
        • "edge shape": selects between lines, wedges, quadratic curves, and cubic curves + * for drawing edges. + *
        • "fill edge shapes": if checked, fills the edge shapes. This will have no effect + * if "line" is selected. + *
        • "edge paint": selects between solid colored edges, and gradient-painted edges. + * Gradient painted edges are darkest in the middle for undirected edges, and darkest + * at the destination for directed edges. + *
        • "show edges": only edges of the checked types are drawn. + *
        • "show arrows": only arrows whose edges are of the checked types are drawn. + *
        • "edge weight highlighting": if checked, edges with weight greater than + * a threshold value are drawn using thick solid lines, and other edges are drawn + * using thin gray dotted lines. (This combines edge stroke and paint.) Otherwise, + * all edges are drawn with thin solid lines. + *
        • "show edge weights": if checked, edges are labeled with their weights. + * Otherwise, edges are not labeled. + *
        + *
      • Miscellaneous (center panel) + *
          + *
        • "bold text": if checked, all vertex and edge labels are drawn using a + * boldface font. Otherwise, a normal-weight font is used. (Has no effect if + * no labels are currently visible.) + *
        • zoom controls: + *
            + *
          • "+" zooms in, "-" zooms out + *
          • "zoom at mouse (wheel only)": if checked, zooming (using the mouse + * scroll wheel) is centered on the location of the mouse pointer; otherwise, + * it is centered on the center of the visualization pane. + *
          + *
        + *
      + * + * + * @author Danyel Fisher, Joshua O'Madadhain, Tom Nelson + */ +@SuppressWarnings("serial") +public class PluggableRendererDemo extends JApplet implements ActionListener +{ + protected JCheckBox v_color; + protected JCheckBox e_color; + protected JCheckBox v_stroke; + protected JCheckBox e_uarrow_pred; + protected JCheckBox e_darrow_pred; + protected JCheckBox e_arrow_centered; + protected JCheckBox v_shape; + protected JCheckBox v_size; + protected JCheckBox v_aspect; + protected JCheckBox v_labels; + protected JRadioButton e_line; + protected JRadioButton e_bent; + protected JRadioButton e_wedge; + protected JRadioButton e_quad; + protected JRadioButton e_ortho; + protected JRadioButton e_cubic; + protected JCheckBox e_labels; + protected JCheckBox font; + protected JCheckBox e_show_d; + protected JCheckBox e_show_u; + protected JCheckBox v_small; + protected JCheckBox zoom_at_mouse; + protected JCheckBox fill_edges; + + protected JRadioButton no_gradient; + protected JRadioButton gradient_relative; + + protected static final int GRADIENT_NONE = 0; + protected static final int GRADIENT_RELATIVE = 1; + protected static int gradient_level = GRADIENT_NONE; + + protected SeedFillColor seedFillColor; + protected SeedDrawColor seedDrawColor; + protected EdgeWeightStrokeFunction ewcs; + protected VertexStrokeHighlight vsh; + protected Function vs; + protected Function vs_none; + protected Function es; + protected Function es_none; + protected VertexFontTransformer vff; + protected EdgeFontTransformer eff; + protected VertexShapeSizeAspect vssa; + protected DirectionDisplayPredicate show_edge; + protected DirectionDisplayPredicate show_arrow; + protected VertexDisplayPredicate show_vertex; + protected Predicate,Number>> self_loop; + protected GradientPickedEdgePaintFunction edgeDrawPaint; + protected GradientPickedEdgePaintFunction edgeFillPaint; + protected final static Object VOLTAGE_KEY = "voltages"; + protected final static Object TRANSPARENCY = "transparency"; + + protected Map edge_weight = new HashMap(); + protected Function voltages; + protected Map transparency = new HashMap(); + + protected VisualizationViewer vv; + protected DefaultModalGraphMouse gm; + protected Set seedVertices = new HashSet(); + + private Graph graph; + + public void start() + { + getContentPane().add( startFunction() ); + } + + public static void main(String[] s ) + { + JFrame jf = new JFrame(); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JPanel jp = new PluggableRendererDemo().startFunction(); + jf.getContentPane().add(jp); + jf.pack(); + jf.setVisible(true); + } + + + public JPanel startFunction() { + this.graph = buildGraph(); + + Layout layout = new FRLayout(graph); + vv = new VisualizationViewer(layout); + + vv.getRenderer().setVertexRenderer(new CachingVertexRenderer(vv)); + vv.getRenderer().setEdgeRenderer(new CachingEdgeRenderer(vv)); + + PickedState picked_state = vv.getPickedVertexState(); + + self_loop = new SelfLoopEdgePredicate(); + // create decorators + seedFillColor = new SeedFillColor(picked_state); + seedDrawColor = new SeedDrawColor(); + ewcs = + new EdgeWeightStrokeFunction(edge_weight); + vsh = new VertexStrokeHighlight(graph, picked_state); + vff = new VertexFontTransformer(); + eff = new EdgeFontTransformer(); + vs_none = Functions.constant(null); + es_none = Functions.constant(null); + vssa = new VertexShapeSizeAspect(graph, voltages); + show_edge = new DirectionDisplayPredicate(true, true); + show_arrow = new DirectionDisplayPredicate(true, false); + show_vertex = new VertexDisplayPredicate(false); + + // uses a gradient edge if unpicked, otherwise uses picked selection + edgeDrawPaint = + new GradientPickedEdgePaintFunction( + new PickableEdgePaintTransformer( + vv.getPickedEdgeState(),Color.black,Color.cyan), vv); + edgeFillPaint = + new GradientPickedEdgePaintFunction( + new PickableEdgePaintTransformer( + vv.getPickedEdgeState(),Color.black,Color.cyan), vv); + + vv.getRenderContext().setVertexFillPaintTransformer(seedFillColor); + vv.getRenderContext().setVertexDrawPaintTransformer(seedDrawColor); + vv.getRenderContext().setVertexStrokeTransformer(vsh); + vv.getRenderContext().setVertexLabelTransformer(vs_none); + vv.getRenderContext().setVertexFontTransformer(vff); + vv.getRenderContext().setVertexShapeTransformer(vssa); + vv.getRenderContext().setVertexIncludePredicate(show_vertex); + + vv.getRenderContext().setEdgeDrawPaintTransformer( edgeDrawPaint ); + vv.getRenderContext().setEdgeLabelTransformer(es_none); + vv.getRenderContext().setEdgeFontTransformer(eff); + vv.getRenderContext().setEdgeStrokeTransformer(ewcs); + vv.getRenderContext().setEdgeIncludePredicate(show_edge); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + vv.getRenderContext().setEdgeArrowPredicate(show_arrow); + + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + vv.getRenderContext().setArrowDrawPaintTransformer(Functions.constant(Color.black)); + JPanel jp = new JPanel(); + jp.setLayout(new BorderLayout()); + + vv.setBackground(Color.white); + GraphZoomScrollPane scrollPane = new GraphZoomScrollPane(vv); + jp.add(scrollPane); + gm = new DefaultModalGraphMouse(); + vv.setGraphMouse(gm); + gm.add(new PopupGraphMousePlugin()); + + addBottomControls( jp ); + vssa.setScaling(true); + + vv.setVertexToolTipTransformer(new VoltageTips()); + vv.setToolTipText("
      Use the mouse wheel to zoom

      Click and Drag the mouse to pan

      Shift-click and Drag to Rotate

      "); + + + + return jp; + } + + /** + * Generates a mixed-mode random graph, runs VoltageRanker on it, and + * returns the resultant graph. + * @return the generated graph + */ + public Graph buildGraph() { + Supplier> graphFactory = + new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + Supplier vertexFactory = + new Supplier() { + int count; + public Integer get() { + return count++; + }}; + Supplier edgeFactory = + new Supplier() { + int count; + public Number get() { + return count++; + }}; + Graph g = + MixedRandomGraphGenerator.generateMixedRandomGraph(graphFactory, vertexFactory, edgeFactory, + edge_weight, 20, seedVertices); + es = new NumberFormattingTransformer(Functions.forMap(edge_weight)); + + // collect the seeds used to define the random graph + + if (seedVertices.size() < 2) + System.out.println("need at least 2 seeds (one source, one sink)"); + + // use these seeds as source and sink vertices, run VoltageRanker + boolean source = true; + Set sources = new HashSet(); + Set sinks = new HashSet(); + for(Integer v : seedVertices) + { + if (source) + sources.add(v); + else + sinks.add(v); + source = !source; + } + VoltageScorer voltage_scores = + new VoltageScorer(g, + Functions.forMap(edge_weight), sources, sinks); + voltage_scores.evaluate(); + voltages = new VertexScoreTransformer(voltage_scores); + vs = new NumberFormattingTransformer(voltages); + + Collection verts = g.getVertices(); + + // assign a transparency value of 0.9 to all vertices + for(Integer v : verts) { + transparency.put(v, new Double(0.9)); + } + + // add a couple of self-loops (sanity check on rendering) + Integer v = verts.iterator().next(); + Number e = new Float(Math.random()); + edge_weight.put(e, e); + g.addEdge(e, v, v); + e = new Float(Math.random()); + edge_weight.put(e, e); + g.addEdge(e, v, v); + return g; + } + + /** + * @param jp panel to which controls will be added + */ + protected void addBottomControls(final JPanel jp) + { + final JPanel control_panel = new JPanel(); + jp.add(control_panel, BorderLayout.EAST); + control_panel.setLayout(new BorderLayout()); + final Box vertex_panel = Box.createVerticalBox(); + vertex_panel.setBorder(BorderFactory.createTitledBorder("Vertices")); + final Box edge_panel = Box.createVerticalBox(); + edge_panel.setBorder(BorderFactory.createTitledBorder("Edges")); + final Box both_panel = Box.createVerticalBox(); + + control_panel.add(vertex_panel, BorderLayout.NORTH); + control_panel.add(edge_panel, BorderLayout.SOUTH); + control_panel.add(both_panel, BorderLayout.CENTER); + + // set up vertex controls + v_color = new JCheckBox("seed highlight"); + v_color.addActionListener(this); + v_stroke = new JCheckBox("stroke highlight on selection"); + v_stroke.addActionListener(this); + v_labels = new JCheckBox("show voltage values"); + v_labels.addActionListener(this); + v_shape = new JCheckBox("shape by degree"); + v_shape.addActionListener(this); + v_size = new JCheckBox("size by voltage"); + v_size.addActionListener(this); + v_size.setSelected(true); + v_aspect = new JCheckBox("stretch by degree ratio"); + v_aspect.addActionListener(this); + v_small = new JCheckBox("filter when degree < " + VertexDisplayPredicate.MIN_DEGREE); + v_small.addActionListener(this); + + vertex_panel.add(v_color); + vertex_panel.add(v_stroke); + vertex_panel.add(v_labels); + vertex_panel.add(v_shape); + vertex_panel.add(v_size); + vertex_panel.add(v_aspect); + vertex_panel.add(v_small); + + // set up edge controls + JPanel gradient_panel = new JPanel(new GridLayout(1, 0)); + gradient_panel.setBorder(BorderFactory.createTitledBorder("Edge paint")); + no_gradient = new JRadioButton("Solid color"); + no_gradient.addActionListener(this); + no_gradient.setSelected(true); +// gradient_absolute = new JRadioButton("Absolute gradient"); +// gradient_absolute.addActionListener(this); + gradient_relative = new JRadioButton("Gradient"); + gradient_relative.addActionListener(this); + ButtonGroup bg_grad = new ButtonGroup(); + bg_grad.add(no_gradient); + bg_grad.add(gradient_relative); + //bg_grad.add(gradient_absolute); + gradient_panel.add(no_gradient); + //gradientGrid.add(gradient_absolute); + gradient_panel.add(gradient_relative); + + JPanel shape_panel = new JPanel(new GridLayout(3,2)); + shape_panel.setBorder(BorderFactory.createTitledBorder("Edge shape")); + e_line = new JRadioButton("line"); + e_line.addActionListener(this); + e_line.setSelected(true); +// e_bent = new JRadioButton("bent line"); +// e_bent.addActionListener(this); + e_wedge = new JRadioButton("wedge"); + e_wedge.addActionListener(this); + e_quad = new JRadioButton("quad curve"); + e_quad.addActionListener(this); + e_cubic = new JRadioButton("cubic curve"); + e_cubic.addActionListener(this); + e_ortho = new JRadioButton("orthogonal"); + e_ortho.addActionListener(this); + ButtonGroup bg_shape = new ButtonGroup(); + bg_shape.add(e_line); +// bg.add(e_bent); + bg_shape.add(e_wedge); + bg_shape.add(e_quad); + bg_shape.add(e_ortho); + bg_shape.add(e_cubic); + shape_panel.add(e_line); +// shape_panel.add(e_bent); + shape_panel.add(e_wedge); + shape_panel.add(e_quad); + shape_panel.add(e_cubic); + shape_panel.add(e_ortho); + fill_edges = new JCheckBox("fill edge shapes"); + fill_edges.setSelected(false); + fill_edges.addActionListener(this); + shape_panel.add(fill_edges); + shape_panel.setOpaque(true); + e_color = new JCheckBox("highlight edge weights"); + e_color.addActionListener(this); + e_labels = new JCheckBox("show edge weight values"); + e_labels.addActionListener(this); + e_uarrow_pred = new JCheckBox("undirected"); + e_uarrow_pred.addActionListener(this); + e_darrow_pred = new JCheckBox("directed"); + e_darrow_pred.addActionListener(this); + e_darrow_pred.setSelected(true); + e_arrow_centered = new JCheckBox("centered"); + e_arrow_centered.addActionListener(this); + JPanel arrow_panel = new JPanel(new GridLayout(1,0)); + arrow_panel.setBorder(BorderFactory.createTitledBorder("Show arrows")); + arrow_panel.add(e_uarrow_pred); + arrow_panel.add(e_darrow_pred); + arrow_panel.add(e_arrow_centered); + + e_show_d = new JCheckBox("directed"); + e_show_d.addActionListener(this); + e_show_d.setSelected(true); + e_show_u = new JCheckBox("undirected"); + e_show_u.addActionListener(this); + e_show_u.setSelected(true); + JPanel show_edge_panel = new JPanel(new GridLayout(1,0)); + show_edge_panel.setBorder(BorderFactory.createTitledBorder("Show edges")); + show_edge_panel.add(e_show_u); + show_edge_panel.add(e_show_d); + + shape_panel.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(shape_panel); + gradient_panel.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(gradient_panel); + show_edge_panel.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(show_edge_panel); + arrow_panel.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(arrow_panel); + + e_color.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(e_color); + e_labels.setAlignmentX(Component.LEFT_ALIGNMENT); + edge_panel.add(e_labels); + + // set up zoom controls + zoom_at_mouse = new JCheckBox("
      zoom at mouse

      (wheel only)

      "); + zoom_at_mouse.addActionListener(this); + zoom_at_mouse.setSelected(true); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JPanel zoomPanel = new JPanel(); + zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom")); + plus.setAlignmentX(Component.CENTER_ALIGNMENT); + zoomPanel.add(plus); + minus.setAlignmentX(Component.CENTER_ALIGNMENT); + zoomPanel.add(minus); + zoom_at_mouse.setAlignmentX(Component.CENTER_ALIGNMENT); + zoomPanel.add(zoom_at_mouse); + + JPanel fontPanel = new JPanel(); + // add font and zoom controls to center panel + font = new JCheckBox("bold text"); + font.addActionListener(this); + font.setAlignmentX(Component.CENTER_ALIGNMENT); + fontPanel.add(font); + + both_panel.add(zoomPanel); + both_panel.add(fontPanel); + + JComboBox modeBox = gm.getModeComboBox(); + modeBox.setAlignmentX(Component.CENTER_ALIGNMENT); + JPanel modePanel = new JPanel(new BorderLayout()) { + public Dimension getMaximumSize() { + return getPreferredSize(); + } + }; + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + JPanel comboGrid = new JPanel(new GridLayout(0,1)); + comboGrid.add(modePanel); + fontPanel.add(comboGrid); + + + JComboBox cb = new JComboBox(); + cb.addItem(Renderer.VertexLabel.Position.N); + cb.addItem(Renderer.VertexLabel.Position.NE); + cb.addItem(Renderer.VertexLabel.Position.E); + cb.addItem(Renderer.VertexLabel.Position.SE); + cb.addItem(Renderer.VertexLabel.Position.S); + cb.addItem(Renderer.VertexLabel.Position.SW); + cb.addItem(Renderer.VertexLabel.Position.W); + cb.addItem(Renderer.VertexLabel.Position.NW); + cb.addItem(Renderer.VertexLabel.Position.N); + cb.addItem(Renderer.VertexLabel.Position.CNTR); + cb.addItem(Renderer.VertexLabel.Position.AUTO); + cb.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + Renderer.VertexLabel.Position position = + (Renderer.VertexLabel.Position)e.getItem(); + vv.getRenderer().getVertexLabelRenderer().setPosition(position); + vv.repaint(); + }}); + cb.setSelectedItem(Renderer.VertexLabel.Position.SE); + JPanel positionPanel = new JPanel(); + positionPanel.setBorder(BorderFactory.createTitledBorder("Label Position")); + positionPanel.add(cb); + + comboGrid.add(positionPanel); + + } + + public void actionPerformed(ActionEvent e) + { + AbstractButton source = (AbstractButton)e.getSource(); + if (source == v_color) + { + seedFillColor.setSeedColoring(source.isSelected()); + } + else if (source == e_color) + { + ewcs.setWeighted(source.isSelected()); + } + else if (source == v_stroke) + { + vsh.setHighlight(source.isSelected()); + } + else if (source == v_labels) + { + if (source.isSelected()) + vv.getRenderContext().setVertexLabelTransformer(vs); + else + vv.getRenderContext().setVertexLabelTransformer(vs_none); + } + else if (source == e_labels) + { + if (source.isSelected()) + vv.getRenderContext().setEdgeLabelTransformer(es); + else + vv.getRenderContext().setEdgeLabelTransformer(es_none); + } + else if (source == e_uarrow_pred) + { + show_arrow.showUndirected(source.isSelected()); + } + else if (source == e_darrow_pred) + { + show_arrow.showDirected(source.isSelected()); + } + else if (source == e_arrow_centered) + { + if(source.isSelected()) + { + vv.getRenderer().getEdgeRenderer().setEdgeArrowRenderingSupport( + new CenterEdgeArrowRenderingSupport()); + } + else + { + vv.getRenderer().getEdgeRenderer().setEdgeArrowRenderingSupport( + new BasicEdgeArrowRenderingSupport()); + } + } + else if (source == font) + { + vff.setBold(source.isSelected()); + eff.setBold(source.isSelected()); + } + else if (source == v_shape) + { + vssa.useFunnyShapes(source.isSelected()); + } + else if (source == v_size) + { + vssa.setScaling(source.isSelected()); + } + else if (source == v_aspect) + { + vssa.setStretching(source.isSelected()); + } + else if (source == e_line) + { + if(source.isSelected()) + { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + } + } + else if (source == e_ortho) + { + if (source.isSelected()) + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.orthogonal(graph)); + } + else if (source == e_wedge) + { + if (source.isSelected()) + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.wedge(graph, 10)); + } +// else if (source == e_bent) +// { +// if(source.isSelected()) +// { +// vv.getRenderContext().setEdgeShapeFunction(new EdgeShape.BentLine()); +// } +// } + else if (source == e_quad) + { + if(source.isSelected()) + { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.quadCurve(graph)); + } + } + else if (source == e_cubic) + { + if(source.isSelected()) + { + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.cubicCurve(graph)); + } + } + else if (source == e_show_d) + { + show_edge.showDirected(source.isSelected()); + } + else if (source == e_show_u) + { + show_edge.showUndirected(source.isSelected()); + } + else if (source == v_small) + { + show_vertex.filterSmall(source.isSelected()); + } + else if(source == zoom_at_mouse) + { + gm.setZoomAtMouse(source.isSelected()); + } + else if (source == no_gradient) { + if (source.isSelected()) { + gradient_level = GRADIENT_NONE; + } + } + else if (source == gradient_relative) { + if (source.isSelected()) { + gradient_level = GRADIENT_RELATIVE; + } + } + else if (source == fill_edges) + { + if(source.isSelected()) { + vv.getRenderContext().setEdgeFillPaintTransformer( edgeFillPaint ); + } else { + vv.getRenderContext().setEdgeFillPaintTransformer( Functions.constant(null) ); + } + } + vv.repaint(); + } + + private final class SeedDrawColor implements Function + { + public Paint apply(V v) + { + return Color.BLACK; + } + } + + private final class SeedFillColor implements Function + { + protected PickedInfo pi; + protected final static float dark_value = 0.8f; + protected final static float light_value = 0.2f; + protected boolean seed_coloring; + + public SeedFillColor(PickedInfo pi) + { + this.pi = pi; + seed_coloring = false; + } + + public void setSeedColoring(boolean b) + { + this.seed_coloring = b; + } + + public Paint apply(V v) + { + float alpha = transparency.get(v).floatValue(); + if (pi.isPicked(v)) + { + return new Color(1f, 1f, 0, alpha); + } + else + { + if (seed_coloring && seedVertices.contains(v)) + { + Color dark = new Color(0, 0, dark_value, alpha); + Color light = new Color(0, 0, light_value, alpha); + return new GradientPaint( 0, 0, dark, 10, 0, light, true); + } + else + return new Color(1f, 0, 0, alpha); + } + + } + } + + private final static class EdgeWeightStrokeFunction + implements Function + { + protected static final Stroke basic = new BasicStroke(1); + protected static final Stroke heavy = new BasicStroke(2); + protected static final Stroke dotted = RenderContext.DOTTED; + + protected boolean weighted = false; + protected Map edge_weight; + + public EdgeWeightStrokeFunction(Map edge_weight) + { + this.edge_weight = edge_weight; + } + + public void setWeighted(boolean weighted) + { + this.weighted = weighted; + } + + public Stroke apply(E e) + { + if (weighted) + { + if (drawHeavy(e)) + return heavy; + else + return dotted; + } + else + return basic; + } + + protected boolean drawHeavy(E e) + { + double value = edge_weight.get(e).doubleValue(); + if (value > 0.7) + return true; + else + return false; + } + + } + + private final static class VertexStrokeHighlight implements + Function + { + protected boolean highlight = false; + protected Stroke heavy = new BasicStroke(5); + protected Stroke medium = new BasicStroke(3); + protected Stroke light = new BasicStroke(1); + protected PickedInfo pi; + protected Graph graph; + + public VertexStrokeHighlight(Graph graph, PickedInfo pi) + { + this.graph = graph; + this.pi = pi; + } + + public void setHighlight(boolean highlight) + { + this.highlight = highlight; + } + + public Stroke apply(V v) + { + if (highlight) + { + if (pi.isPicked(v)) + return heavy; + else + { + for(V w : graph.getNeighbors(v)) { +// for (Iterator iter = graph.getNeighbors(v)v.getNeighbors().iterator(); iter.hasNext(); ) +// { +// Vertex w = (Vertex)iter.next(); + if (pi.isPicked(w)) + return medium; + } + return light; + } + } + else + return light; + } + + } + + private final static class VertexFontTransformer + implements Function + { + protected boolean bold = false; + Font f = new Font("Helvetica", Font.PLAIN, 12); + Font b = new Font("Helvetica", Font.BOLD, 12); + + public void setBold(boolean bold) + { + this.bold = bold; + } + + public Font apply(V v) + { + if (bold) + return b; + else + return f; + } + } + + private final static class EdgeFontTransformer + implements Function +{ + protected boolean bold = false; + Font f = new Font("Helvetica", Font.PLAIN, 12); + Font b = new Font("Helvetica", Font.BOLD, 12); + + public void setBold(boolean bold) + { + this.bold = bold; + } + + public Font apply(E e) + { + if (bold) + return b; + else + return f; + } +} + private final static class DirectionDisplayPredicate + implements Predicate,E>> + //extends AbstractGraphPredicate + { + protected boolean show_d; + protected boolean show_u; + + public DirectionDisplayPredicate(boolean show_d, boolean show_u) + { + this.show_d = show_d; + this.show_u = show_u; + } + + public void showDirected(boolean b) + { + show_d = b; + } + + public void showUndirected(boolean b) + { + show_u = b; + } + + public boolean apply(Context,E> context) + { + Graph graph = context.graph; + E e = context.element; + if (graph.getEdgeType(e) == EdgeType.DIRECTED && show_d) { + return true; + } + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED && show_u) { + return true; + } + return false; + } + } + + private final static class VertexDisplayPredicate + implements Predicate,V>> +// extends AbstractGraphPredicate + { + protected boolean filter_small; + protected final static int MIN_DEGREE = 4; + + public VertexDisplayPredicate(boolean filter) + { + this.filter_small = filter; + } + + public void filterSmall(boolean b) + { + filter_small = b; + } + + public boolean apply(Context,V> context) { + Graph graph = context.graph; + V v = context.element; +// Vertex v = (Vertex)arg0; + if (filter_small) + return (graph.degree(v) >= MIN_DEGREE); + else + return true; + } + } + + /** + * Controls the shape, size, and aspect ratio for each vertex. + * + * @author Joshua O'Madadhain + */ + private final static class VertexShapeSizeAspect + extends AbstractVertexShapeTransformer + implements Function { + + protected boolean stretch = false; + protected boolean scale = false; + protected boolean funny_shapes = false; + protected Function voltages; + protected Graph graph; +// protected AffineTransform scaleTransform = new AffineTransform(); + + public VertexShapeSizeAspect(Graph graphIn, Function voltagesIn) + { + this.graph = graphIn; + this.voltages = voltagesIn; + setSizeTransformer(new Function() { + + public Integer apply(V v) { + if (scale) + return (int)(voltages.apply(v) * 30) + 20; + else + return 20; + + }}); + setAspectRatioTransformer(new Function() { + + public Float apply(V v) { + if (stretch) { + return (float)(graph.inDegree(v) + 1) / + (graph.outDegree(v) + 1); + } else { + return 1.0f; + } + }}); + } + + public void setStretching(boolean stretch) + { + this.stretch = stretch; + } + + public void setScaling(boolean scale) + { + this.scale = scale; + } + + public void useFunnyShapes(boolean use) + { + this.funny_shapes = use; + } + + public Shape apply(V v) + { + if (funny_shapes) + { + if (graph.degree(v) < 5) + { + int sides = Math.max(graph.degree(v), 3); + return factory.getRegularPolygon(v, sides); + } + else + return factory.getRegularStar(v, graph.degree(v)); + } + else + return factory.getEllipse(v); + } + } + + /** + * a GraphMousePlugin that offers popup + * menu support + */ + protected class PopupGraphMousePlugin extends AbstractPopupGraphMousePlugin + implements MouseListener { + + public PopupGraphMousePlugin() { + this(MouseEvent.BUTTON3_MASK); + } + public PopupGraphMousePlugin(int modifiers) { + super(modifiers); + } + + /** + * If this event is over a Vertex, pop up a menu to + * allow the user to increase/decrease the voltage + * attribute of this Vertex + * @param e the event to be handled + */ + @SuppressWarnings("unchecked") + protected void handlePopup(MouseEvent e) { + final VisualizationViewer vv = + (VisualizationViewer)e.getSource(); + Point2D p = e.getPoint();//vv.getRenderContext().getBasicTransformer().inverseViewTransform(e.getPoint()); + + GraphElementAccessor pickSupport = vv.getPickSupport(); + if(pickSupport != null) { + final Integer v = pickSupport.getVertex(vv.getGraphLayout(), p.getX(), p.getY()); + if(v != null) { + JPopupMenu popup = new JPopupMenu(); + popup.add(new AbstractAction("Decrease Transparency") { + public void actionPerformed(ActionEvent e) { + Double value = Math.min(1, + transparency.get(v).doubleValue()+0.1); + transparency.put(v, value); +// transparency.put(v, )transparency.get(v); +// MutableDouble value = (MutableDouble)transparency.getNumber(v); +// value.setDoubleValue(Math.min(1, value.doubleValue() + 0.1)); + vv.repaint(); + } + }); + popup.add(new AbstractAction("Increase Transparency"){ + public void actionPerformed(ActionEvent e) { + Double value = Math.max(0, + transparency.get(v).doubleValue()-0.1); + transparency.put(v, value); +// MutableDouble value = (MutableDouble)transparency.getNumber(v); +// value.setDoubleValue(Math.max(0, value.doubleValue() - 0.1)); + vv.repaint(); + } + }); + popup.show(vv, e.getX(), e.getY()); + } else { + final Number edge = pickSupport.getEdge(vv.getGraphLayout(), p.getX(), p.getY()); + if(edge != null) { + JPopupMenu popup = new JPopupMenu(); + popup.add(new AbstractAction(edge.toString()) { + public void actionPerformed(ActionEvent e) { + System.err.println("got "+edge); + } + }); + popup.show(vv, e.getX(), e.getY()); + + } + } + } + } + } + + public class VoltageTips + implements Function { + + public String apply(Integer vertex) { + return "Voltage:"+voltages.apply(vertex); + } + } + + public class GradientPickedEdgePaintFunction extends GradientEdgePaintTransformer + { + private Function defaultFunc; + protected boolean fill_edge = false; + Predicate,E>> selfLoop = new SelfLoopEdgePredicate(); + + public GradientPickedEdgePaintFunction(Function defaultEdgePaintFunction, + VisualizationViewer vv) + { + super(Color.WHITE, Color.BLACK, vv); + this.defaultFunc = defaultEdgePaintFunction; + } + + public void useFill(boolean b) + { + fill_edge = b; + } + + public Paint apply(E e) { + if (gradient_level == GRADIENT_NONE) { + return defaultFunc.apply(e); + } else { + return super.apply(e); + } + } + + protected Color getColor2(E e) + { + return vv.getPickedEdgeState().isPicked(e)? Color.CYAN : c2; + } + +// public Paint getFillPaint(E e) +// { +// if (selfLoop.evaluateEdge(vv.getGraphLayout().getGraph(), e) || !fill_edge) +// return null; +// else +// return getDrawPaint(e); +// } + + } + +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/RadialTreeLensDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/RadialTreeLensDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/RadialTreeLensDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/RadialTreeLensDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.transform.LensSupport; +import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport; + +/** + * Shows a RadialTreeLayout view of a Forest. + * A hyperbolic projection lens may also be applied + * to the view + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class RadialTreeLensDemo extends JApplet { + + Forest graph; + + Supplier> graphFactory = + new Supplier>() { + + public DirectedGraph get() { + return new DirectedSparseGraph(); + } + }; + + Supplier> treeFactory = + new Supplier> () { + + public Tree get() { + return new DelegateTree(graphFactory); + } + }; + Supplier edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + } + }; + + Supplier vertexFactory = new Supplier() { + int i=0; + public String get() { + return "V"+i++; + } + }; + + VisualizationServer.Paintable rings; + + String root; + + TreeLayout layout; + + RadialTreeLayout radialLayout; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * provides a Hyperbolic lens for the view + */ + LensSupport hyperbolicViewSupport; + + ScalingControl scaler; + + /** + * create an instance of a simple graph with controls to + * demo the zoomand hyperbolic features. + * + */ + public RadialTreeLensDemo() { + + // create a simple graph for the demo + // create a simple graph for the demo + graph = new DelegateForest(); + + createTree(); + + layout = new TreeLayout(graph); + radialLayout = new RadialTreeLayout(graph); + radialLayout.setSize(new Dimension(600,600)); + + Dimension preferredSize = new Dimension(600,600); + + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(radialLayout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + PickedState ps = vv.getPickedVertexState(); + PickedState pes = vv.getPickedEdgeState(); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(ps, Color.red, Color.yellow)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.cyan)); + vv.setBackground(Color.white); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + rings = new Rings(); + vv.addPreRenderPaintable(rings); + + hyperbolicViewSupport = + new ViewLensSupport(vv, new HyperbolicShapeTransformer(vv, + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), + new ModalLensGraphMouse()); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + final JRadioButton hyperView = new JRadioButton("Hyperbolic View"); + hyperView.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED); + } + }); + + graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener()); + + JMenuBar menubar = new JMenuBar(); + menubar.add(graphMouse.getModeMenu()); + gzsp.setCorner(menubar); + + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel hyperControls = new JPanel(new GridLayout(3,2)); + hyperControls.setBorder(BorderFactory.createTitledBorder("Examiner Lens")); + zoomControls.add(plus); + zoomControls.add(minus); + JPanel modeControls = new JPanel(new BorderLayout()); + modeControls.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modeControls.add(graphMouse.getModeComboBox()); + hyperControls.add(hyperView); + + controls.add(zoomControls); + controls.add(hyperControls); + controls.add(modeControls); + content.add(controls, BorderLayout.SOUTH); + } + + private void createTree() { + graph.addVertex("V0"); + graph.addEdge(edgeFactory.get(), "V0", "V1"); + graph.addEdge(edgeFactory.get(), "V0", "V2"); + graph.addEdge(edgeFactory.get(), "V1", "V4"); + graph.addEdge(edgeFactory.get(), "V2", "V3"); + graph.addEdge(edgeFactory.get(), "V2", "V5"); + graph.addEdge(edgeFactory.get(), "V4", "V6"); + graph.addEdge(edgeFactory.get(), "V4", "V7"); + graph.addEdge(edgeFactory.get(), "V3", "V8"); + graph.addEdge(edgeFactory.get(), "V6", "V9"); + graph.addEdge(edgeFactory.get(), "V4", "V10"); + + graph.addVertex("A0"); + graph.addEdge(edgeFactory.get(), "A0", "A1"); + graph.addEdge(edgeFactory.get(), "A0", "A2"); + graph.addEdge(edgeFactory.get(), "A0", "A3"); + + graph.addVertex("B0"); + graph.addEdge(edgeFactory.get(), "B0", "B1"); + graph.addEdge(edgeFactory.get(), "B0", "B2"); + graph.addEdge(edgeFactory.get(), "B1", "B4"); + graph.addEdge(edgeFactory.get(), "B2", "B3"); + graph.addEdge(edgeFactory.get(), "B2", "B5"); + graph.addEdge(edgeFactory.get(), "B4", "B6"); + graph.addEdge(edgeFactory.get(), "B4", "B7"); + graph.addEdge(edgeFactory.get(), "B3", "B8"); + graph.addEdge(edgeFactory.get(), "B6", "B9"); + + } + + class Rings implements VisualizationServer.Paintable { + + Collection depths; + + public Rings() { + depths = getDepths(); + } + + private Collection getDepths() { + Set depths = new HashSet(); + Map polarLocations = radialLayout.getPolarLocations(); + for(String v : graph.getVertices()) { + PolarPoint pp = polarLocations.get(v); + depths.add(pp.getRadius()); + } + return depths; + } + + public void paint(Graphics g) { + g.setColor(Color.gray); + Graphics2D g2d = (Graphics2D)g; + Point2D center = radialLayout.getCenter(); + + Ellipse2D ellipse = new Ellipse2D.Double(); + for(double d : depths) { + ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, + center.getX()+d, center.getY()+d); + Shape shape = + vv.getRenderContext().getMultiLayerTransformer().transform(ellipse); + g2d.draw(shape); + } + } + + public boolean useTransform() { + return true; + } + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new RadialTreeLensDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SatelliteViewDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SatelliteViewDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SatelliteViewDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SatelliteViewDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.GeneralPath; + +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.ToolTipManager; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.SatelliteVisualizationViewer; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; + +/** + * Demonstrates the construction of a graph visualization with a main and + * a satellite view. The satellite + * view is smaller, always contains the entire graph, and contains + * a lens shape that shows the boundaries of the visible part of the + * graph in the main view. Using the mouse, you can pick, translate, + * layout-scale, view-scale, rotate, shear, and region-select in either + * view. Using the mouse in either window affects only the main view + * and the lens shape in the satellite view. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class SatelliteViewDemo extends JApplet { + + static final String instructions = + ""+ + "

      Instructions for Mouse Listeners

      "+ + "

      There are two modes, Transforming and Picking."+ + "

      The modes are selected with a combo box."+ + + "

      Transforming Mode:"+ + "

        "+ + "
      • Mouse1+drag pans the graph"+ + "
      • Mouse1+Shift+drag rotates the graph"+ + "
      • Mouse1+CTRL(or Command)+drag shears the graph"+ + "
      "+ + + "Picking Mode:"+ + "
        "+ + "
      • Mouse1 on a Vertex selects the vertex"+ + "
      • Mouse1 elsewhere unselects all Vertices"+ + "
      • Mouse1+Shift on a Vertex adds/removes Vertex selection"+ + "
      • Mouse1+drag on a Vertex moves all selected Vertices"+ + "
      • Mouse1+drag elsewhere selects Vertices in a region"+ + "
      • Mouse1+Shift+drag adds selection of Vertices in a new region"+ + "
      • Mouse1+CTRL on a Vertex selects the vertex and centers the display on it"+ + "
      "+ + "Both Modes:"+ + "
        "+ + "
      • Mousewheel scales with a crossover value of 1.0.

        "+ + " - scales the graph layout when the combined scale is greater than 1

        "+ + " - scales the graph view when the combined scale is less than 1"; + + JDialog helpDialog; + + Paintable viewGrid; + + /** + * create an instance of a simple graph in two views with controls to + * demo the features. + * + */ + public SatelliteViewDemo() { + + // create a simple graph for the demo + Graph graph = TestGraphs.getOneComponentGraph(); + + // the preferred sizes for the two views + Dimension preferredSize1 = new Dimension(600,600); + Dimension preferredSize2 = new Dimension(300, 300); + + // create one layout for the graph + FRLayout layout = new FRLayout(graph); + layout.setMaxIterations(500); + + // create one model that both views will share + VisualizationModel vm = + new DefaultVisualizationModel(layout, preferredSize1); + + // create 2 views that share the same model + final VisualizationViewer vv1 = + new VisualizationViewer(vm, preferredSize1); + final SatelliteVisualizationViewer vv2 = + new SatelliteVisualizationViewer(vv1, preferredSize2); + vv1.setBackground(Color.white); + vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv1.getPickedEdgeState(), Color.black, Color.cyan)); + vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv1.getPickedVertexState(), Color.red, Color.yellow)); + vv2.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv2.getPickedEdgeState(), Color.black, Color.cyan)); + vv2.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv2.getPickedVertexState(), Color.red, Color.yellow)); + vv1.getRenderer().setVertexRenderer(new GradientVertexRenderer(Color.red, Color.white, true)); + vv1.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv1.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); + + ScalingControl vv2Scaler = new CrossoverScalingControl(); + vv2.scaleToLayout(vv2Scaler); + + viewGrid = new ViewGrid(vv2, vv1); + + // add default listener for ToolTips + vv1.setVertexToolTipTransformer(new ToStringLabeller()); + vv2.setVertexToolTipTransformer(new ToStringLabeller()); + + vv2.getRenderContext().setVertexLabelTransformer(vv1.getRenderContext().getVertexLabelTransformer()); + + + ToolTipManager.sharedInstance().setDismissDelay(10000); + + Container content = getContentPane(); + Container panel = new JPanel(new BorderLayout()); + Container rightPanel = new JPanel(new GridLayout(2,1)); + + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv1); + panel.add(gzsp); + rightPanel.add(new JPanel()); + rightPanel.add(vv2); + panel.add(rightPanel, BorderLayout.EAST); + + helpDialog = new JDialog(); + helpDialog.getContentPane().add(new JLabel(instructions)); + + // create a GraphMouse for the main view + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + vv1.setGraphMouse(graphMouse); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1.1f, vv1.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1/1.1f, vv1.getCenter()); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(((DefaultModalGraphMouse)vv2.getGraphMouse()) + .getModeListener()); + + JCheckBox gridBox = new JCheckBox("Show Grid"); + gridBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + showGrid(vv2, e.getStateChange() == ItemEvent.SELECTED); + }}); + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + helpDialog.pack(); + helpDialog.setVisible(true); + } + }); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + controls.add(modeBox); + controls.add(gridBox); + controls.add(help); + content.add(panel); + content.add(controls, BorderLayout.SOUTH); + } + + protected void showGrid(VisualizationViewer vv, boolean state) { + if(state == true) { + vv.addPreRenderPaintable(viewGrid); + } else { + vv.removePreRenderPaintable(viewGrid); + } + vv.repaint(); + } + + /** + * draws a grid on the SatelliteViewer's lens + * @author Tom Nelson + * + */ + static class ViewGrid implements Paintable { + + VisualizationViewer master; + VisualizationViewer vv; + + public ViewGrid(VisualizationViewer vv, VisualizationViewer master) { + this.vv = vv; + this.master = master; + } + public void paint(Graphics g) { + ShapeTransformer masterViewTransformer = master.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + ShapeTransformer masterLayoutTransformer = master.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + ShapeTransformer vvLayoutTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + + Rectangle rect = master.getBounds(); + GeneralPath path = new GeneralPath(); + path.moveTo(rect.x, rect.y); + path.lineTo(rect.width,rect.y); + path.lineTo(rect.width, rect.height); + path.lineTo(rect.x, rect.height); + path.lineTo(rect.x, rect.y); + + for(int i=0; i<=rect.width; i+=rect.width/10) { + path.moveTo(rect.x+i, rect.y); + path.lineTo(rect.x+i, rect.height); + } + for(int i=0; i<=rect.height; i+=rect.height/10) { + path.moveTo(rect.x, rect.y+i); + path.lineTo(rect.width, rect.y+i); + } + Shape lens = path; + lens = masterViewTransformer.inverseTransform(lens); + lens = masterLayoutTransformer.inverseTransform(lens); + lens = vvLayoutTransformer.transform(lens); + Graphics2D g2d = (Graphics2D)g; + Color old = g.getColor(); + g.setColor(Color.cyan); + g2d.draw(lens); + + path = new GeneralPath(); + path.moveTo((float)rect.getMinX(), (float)rect.getCenterY()); + path.lineTo((float)rect.getMaxX(), (float)rect.getCenterY()); + path.moveTo((float)rect.getCenterX(), (float)rect.getMinY()); + path.lineTo((float)rect.getCenterX(), (float)rect.getMaxY()); + Shape crosshairShape = path; + crosshairShape = masterViewTransformer.inverseTransform(crosshairShape); + crosshairShape = masterLayoutTransformer.inverseTransform(crosshairShape); + crosshairShape = vvLayoutTransformer.transform(crosshairShape); + g.setColor(Color.black); + g2d.setStroke(new BasicStroke(3)); + g2d.draw(crosshairShape); + + g.setColor(old); + } + + public boolean useTransform() { + return true; + } + } + + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new SatelliteViewDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShortestPathDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShortestPathDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShortestPathDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShortestPathDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,309 @@ +/* + * Created on Jan 2, 2004 + */ +package edu.uci.ics.jung.samples; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Paint; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Point2D; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingConstants; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.random.EppsteinPowerLawGenerator; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.shortestpath.BFSDistanceLabeler; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.Renderer; + +/** + * Demonstrates use of the shortest path algorithm and visualization of the + * results. + * + * @author danyelf + */ +public class ShortestPathDemo extends JPanel { + + /** + * + */ + private static final long serialVersionUID = 7526217664458188502L; + + /** + * Starting vertex + */ + private String mFrom; + + /** + * Ending vertex + */ + private String mTo; + private Graph mGraph; + private Set mPred; + + public ShortestPathDemo() { + + this.mGraph = getGraph(); + setBackground(Color.WHITE); + // show graph + final Layout layout = new FRLayout(mGraph); + final VisualizationViewer vv = new VisualizationViewer(layout); + vv.setBackground(Color.WHITE); + + vv.getRenderContext().setVertexDrawPaintTransformer(new MyVertexDrawPaintFunction()); + vv.getRenderContext().setVertexFillPaintTransformer(new MyVertexFillPaintFunction()); + vv.getRenderContext().setEdgeDrawPaintTransformer(new MyEdgePaintFunction()); + vv.getRenderContext().setEdgeStrokeTransformer(new MyEdgeStrokeFunction()); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.setGraphMouse(new DefaultModalGraphMouse()); + vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){ + + public boolean useTransform() { + return true; + } + public void paint(Graphics g) { + if(mPred == null) return; + + // for all edges, paint edges that are in shortest path + for (Number e : layout.getGraph().getEdges()) { + + if(isBlessed(e)) { + String v1 = mGraph.getEndpoints(e).getFirst(); + String v2 = mGraph.getEndpoints(e).getSecond(); + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + p1 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p1); + p2 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p2); + Renderer renderer = vv.getRenderer(); + renderer.renderEdge( + vv.getRenderContext(), + layout, + e); + } + } + } + }); + + setLayout(new BorderLayout()); + add(vv, BorderLayout.CENTER); + // set up controls + add(setUpControls(), BorderLayout.SOUTH); + } + + boolean isBlessed( Number e ) { + Pair endpoints = mGraph.getEndpoints(e); + String v1= endpoints.getFirst() ; + String v2= endpoints.getSecond() ; + return v1.equals(v2) == false && mPred.contains(v1) && mPred.contains(v2); + } + + /** + * @author danyelf + */ + public class MyEdgePaintFunction implements Function { + + public Paint apply(Number e) { + if ( mPred == null || mPred.size() == 0) return Color.BLACK; + if( isBlessed( e )) { + return new Color(0.0f, 0.0f, 1.0f, 0.5f);//Color.BLUE; + } else { + return Color.LIGHT_GRAY; + } + } + } + + public class MyEdgeStrokeFunction implements Function { + protected final Stroke THIN = new BasicStroke(1); + protected final Stroke THICK = new BasicStroke(1); + + public Stroke apply(Number e) { + if ( mPred == null || mPred.size() == 0) return THIN; + if (isBlessed( e ) ) { + return THICK; + } else + return THIN; + } + + } + + /** + * @author danyelf + */ + public class MyVertexDrawPaintFunction implements Function { + + public Paint apply(V v) { + return Color.black; + } + + } + + public class MyVertexFillPaintFunction implements Function { + + public Paint apply( V v ) { + if ( v == mFrom) { + return Color.BLUE; + } + if ( v == mTo ) { + return Color.BLUE; + } + if ( mPred == null ) { + return Color.LIGHT_GRAY; + } else { + if ( mPred.contains(v)) { + return Color.RED; + } else { + return Color.LIGHT_GRAY; + } + } + } + + } + + /** + * + */ + private JPanel setUpControls() { + JPanel jp = new JPanel(); + jp.setBackground(Color.WHITE); + jp.setLayout(new BoxLayout(jp, BoxLayout.PAGE_AXIS)); + jp.setBorder(BorderFactory.createLineBorder(Color.black, 3)); + jp.add( + new JLabel("Select a pair of vertices for which a shortest path will be displayed")); + JPanel jp2 = new JPanel(); + jp2.add(new JLabel("vertex from", SwingConstants.LEFT)); + jp2.add(getSelectionBox(true)); + jp2.setBackground(Color.white); + JPanel jp3 = new JPanel(); + jp3.add(new JLabel("vertex to", SwingConstants.LEFT)); + jp3.add(getSelectionBox(false)); + jp3.setBackground(Color.white); + jp.add( jp2 ); + jp.add( jp3 ); + return jp; + } + + private Component getSelectionBox(final boolean from) { + + Set s = new TreeSet(); + + for (String v : mGraph.getVertices()) { + s.add(v); + } + final JComboBox choices = new JComboBox((String[]) s.toArray()); + choices.setSelectedIndex(-1); + choices.setBackground(Color.WHITE); + choices.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + String v = (String) choices.getSelectedItem(); + + if (from) { + mFrom = v; + } else { + mTo = v; + } + drawShortest(); + repaint(); + } + }); + return choices; + } + + /** + * + */ + protected void drawShortest() { + if (mFrom == null || mTo == null) { + return; + } + BFSDistanceLabeler bdl = new BFSDistanceLabeler(); + bdl.labelDistances(mGraph, mFrom); + mPred = new HashSet(); + + // grab a predecessor + String v = mTo; + Set prd = bdl.getPredecessors(v); + mPred.add( mTo ); + while( prd != null && prd.size() > 0) { + v = prd.iterator().next(); + mPred.add( v ); + if ( v == mFrom ) return; + prd = bdl.getPredecessors(v); + } + } + + public static void main(String[] s) { + JFrame jf = new JFrame(); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.getContentPane().add(new ShortestPathDemo()); + jf.pack(); + jf.setVisible(true); + } + + /** + * @return the graph for this demo + */ + Graph getGraph() { + + Graph g = + new EppsteinPowerLawGenerator( + new GraphFactory(), new VertexFactory(), new EdgeFactory(), 26, 50, 50).get(); + Set removeMe = new HashSet(); + for (String v : g.getVertices()) { + if ( g.degree(v) == 0 ) { + removeMe.add( v ); + } + } + for(String v : removeMe) { + g.removeVertex(v); + } + return g; + } + + static class GraphFactory implements Supplier> { + public Graph get() { + return new SparseMultigraph(); + } + } + + static class VertexFactory implements Supplier { + char a = 'a'; + public String get() { + return Character.toString(a++); + } + + } + static class EdgeFactory implements Supplier { + int count; + public Number get() { + return count++; + } + + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShowLayouts.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShowLayouts.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShowLayouts.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/ShowLayouts.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JPanel; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.generators.random.MixedRandomGraphGenerator; +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.ISOMLayout; +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout2; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.SparseMultigraph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.util.Animator; + + +/** + * Demonstrates several of the graph layout algorithms. + * Allows the user to interactively select one of several graphs, and one of + * several layouts, and visualizes the combination. + * + * @author Danyel Fisher + * @author Joshua O'Madadhain + */ +@SuppressWarnings("serial") +public class ShowLayouts extends JApplet { + protected static Graph[] g_array; + protected static int graph_index; + protected static String[] graph_names = {"Two component graph", + "Random mixed-mode graph", "Miscellaneous multicomponent graph", + "Random directed acyclic graph", "One component graph", + "Chain+isolate graph", "Trivial (disconnected) graph"}; + + public static class GraphChooser implements ActionListener + { + private JComboBox layout_combo; + + public GraphChooser(JComboBox layout_combo) + { + this.layout_combo = layout_combo; + } + + public void actionPerformed(ActionEvent e) + { + JComboBox cb = (JComboBox)e.getSource(); + graph_index = cb.getSelectedIndex(); + layout_combo.setSelectedIndex(layout_combo.getSelectedIndex()); // rebuild the layout + } + } + + /** + * + * @author danyelf + */ + + private static final class LayoutChooser implements ActionListener + { + private final JComboBox jcb; + private final VisualizationViewer vv; + + private LayoutChooser(JComboBox jcb, VisualizationViewer vv) + { + super(); + this.jcb = jcb; + this.vv = vv; + } + + @SuppressWarnings("unchecked") + public void actionPerformed(ActionEvent arg0) + { + Object[] constructorArgs = + { g_array[graph_index]}; + + Class> layoutC = + (Class>) jcb.getSelectedItem(); + try + { + Constructor> constructor = layoutC + .getConstructor(new Class[] {Graph.class}); + Object o = constructor.newInstance(constructorArgs); + Layout l = (Layout) o; + l.setInitializer(vv.getGraphLayout()); + l.setSize(vv.getSize()); + + LayoutTransition lt = + new LayoutTransition(vv, vv.getGraphLayout(), l); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.repaint(); + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static JPanel getGraphPanel() + { + g_array = + (Graph[]) + new Graph[graph_names.length]; + + Supplier> graphFactory = + new Supplier>() { + public Graph get() { + return new SparseMultigraph(); + } + }; + + Supplier vertexFactory = new Supplier() { + int count; + public Integer get() { + return count++; + }}; + Supplier edgeFactory = new Supplier() { + int count; + public Number get() { + return count++; + }}; + + + g_array[0] = TestGraphs.createTestGraph(false); + g_array[1] = MixedRandomGraphGenerator.generateMixedRandomGraph(graphFactory, + vertexFactory, edgeFactory, new HashMap(), 20, new HashSet()); + g_array[2] = TestGraphs.getDemoGraph(); + g_array[3] = TestGraphs.createDirectedAcyclicGraph(4, 4, 0.3); + g_array[4] = TestGraphs.getOneComponentGraph(); + g_array[5] = TestGraphs.createChainPlusIsolates(18, 5); + g_array[6] = TestGraphs.createChainPlusIsolates(0, 20); + + Graph g = g_array[4]; // initial graph + + final VisualizationViewer vv = + new VisualizationViewer(new FRLayout(g)); + + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.red, Color.yellow)); + + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + JButton reset = new JButton("reset"); + reset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Layout layout = vv.getGraphLayout(); + layout.initialize(); + Relaxer relaxer = vv.getModel().getRelaxer(); + if(relaxer != null) { +// if(layout instanceof IterativeContext) { + relaxer.stop(); + relaxer.prerelax(); + relaxer.relax(); + } + }}); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(((DefaultModalGraphMouse)vv.getGraphMouse()).getModeListener()); + + JPanel jp = new JPanel(); + jp.setBackground(Color.WHITE); + jp.setLayout(new BorderLayout()); + jp.add(vv, BorderLayout.CENTER); + Class[] combos = getCombos(); + final JComboBox jcb = new JComboBox(combos); + // use a renderer to shorten the layout name presentation + jcb.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(valueString.lastIndexOf('.')+1); + return super.getListCellRendererComponent(list, valueString, index, isSelected, + cellHasFocus); + } + }); + jcb.addActionListener(new LayoutChooser(jcb, vv)); + jcb.setSelectedItem(FRLayout.class); + + JPanel control_panel = new JPanel(new GridLayout(2,1)); + JPanel topControls = new JPanel(); + JPanel bottomControls = new JPanel(); + control_panel.add(topControls); + control_panel.add(bottomControls); + jp.add(control_panel, BorderLayout.NORTH); + + final JComboBox graph_chooser = new JComboBox(graph_names); + + graph_chooser.addActionListener(new GraphChooser(jcb)); + + topControls.add(jcb); + topControls.add(graph_chooser); + bottomControls.add(plus); + bottomControls.add(minus); + bottomControls.add(modeBox); + bottomControls.add(reset); + return jp; + } + + public void start() + { + this.getContentPane().add(getGraphPanel()); + } + + /** + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private static Class[] getCombos() + { + List> layouts = new ArrayList>(); + layouts.add(KKLayout.class); + layouts.add(FRLayout.class); + layouts.add(CircleLayout.class); + layouts.add(SpringLayout.class); + layouts.add(SpringLayout2.class); + layouts.add(ISOMLayout.class); + return layouts.toArray(new Class[0]); + } + + public static void main(String[] args) + { + JPanel jp = getGraphPanel(); + + JFrame jf = new JFrame(); + jf.getContentPane().add(jp); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.pack(); + jf.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SimpleGraphDraw.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SimpleGraphDraw.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SimpleGraphDraw.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SimpleGraphDraw.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.samples; + +import java.io.IOException; + +import javax.swing.JFrame; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedSparseGraph; +import edu.uci.ics.jung.io.PajekNetReader; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * A class that shows the minimal work necessary to load and visualize a graph. + */ +public class SimpleGraphDraw +{ + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static void main(String[] args) throws IOException + { + JFrame jf = new JFrame(); + Graph g = getGraph(); + VisualizationViewer vv = new VisualizationViewer(new FRLayout(g)); + jf.getContentPane().add(vv); + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jf.pack(); + jf.setVisible(true); + } + + /** + * Generates a graph: in this case, reads it from the file + * "samples/datasetsgraph/simple.net" + * @return A sample undirected graph + * @throws IOException if there is an error in reading the file + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Graph getGraph() throws IOException + { + PajekNetReader pnr = new PajekNetReader(new Supplier(){ + public Object get() { + return new Object(); + }}); + Graph g = new UndirectedSparseGraph(); + + pnr.load("src/main/resources/datasets/simple.net", g); + return g; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SubLayoutDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SubLayoutDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/SubLayoutDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/SubLayoutDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Point2D; +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.AggregateLayout; +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.PickedState; + +/** + * Demonstrates the AggregateLayout + * class. In this demo, vertices are visually clustered as they + * are selected. The cluster is formed in a new Layout centered at the + * middle locations of the selected vertices. The size and layout + * algorithm for each new cluster is selectable. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class SubLayoutDemo extends JApplet { + + String instructions = + ""+ + "Use the Layout combobox to select the "+ + "

        underlying layout."+ + "

        Use the SubLayout combobox to select "+ + "

        the type of layout for any clusters you create."+ + "

        To create clusters, use the mouse to select "+ + "

        multiple vertices, either by dragging a region, "+ + "

        or by shift-clicking on multiple vertices."+ + "

        After you select vertices, use the "+ + "

        Cluster Picked button to cluster them using the "+ + "

        layout and size specified in the Sublayout comboboxen."+ + "

        Use the Uncluster All button to remove all"+ + "

        clusters."+ + "

        You can drag the cluster with the mouse." + + "

        Use the 'Picking'/'Transforming' combo-box to switch"+ + "

        between picking and transforming mode."; + /** + * the graph + */ + Graph graph; + + Map,Dimension> sizes = new HashMap,Dimension>(); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + Class[] layoutClasses = new Class[] { + CircleLayout.class,SpringLayout.class,FRLayout.class,KKLayout.class + }; + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + AggregateLayout clusteringLayout; + + Dimension subLayoutSize; + + PickedState ps; + + @SuppressWarnings("rawtypes") + Class subLayoutType = CircleLayout.class; + + /** + * create an instance of a simple graph with controls to + * demo the zoomand hyperbolic features. + * + */ + public SubLayoutDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + // ClusteringLayout is a decorator class that delegates + // to another layout, but can also sepately manage the + // layout of sub-sets of vertices in circular clusters. + clusteringLayout = new AggregateLayout(new FRLayout(graph)); + //new SubLayoutDecorator(new FRLayout(graph)); + + Dimension preferredSize = new Dimension(600,600); + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(clusteringLayout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + ps = vv.getPickedVertexState(); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.red)); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), + Color.red, Color.yellow)); + vv.setBackground(Color.white); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + /** + * the regular graph mouse for the normal view + */ + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.PICKING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton cluster = new JButton("Cluster Picked"); + cluster.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + clusterPicked(); + }}); + + JButton uncluster = new JButton("UnCluster All"); + uncluster.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + uncluster(); + }}); + + JComboBox layoutTypeComboBox = new JComboBox(layoutClasses); + layoutTypeComboBox.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(valueString.lastIndexOf('.')+1); + return super.getListCellRendererComponent(list, valueString, index, isSelected, + cellHasFocus); + } + }); + layoutTypeComboBox.setSelectedItem(FRLayout.class); + layoutTypeComboBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + @SuppressWarnings({ "unchecked", "rawtypes" }) + Class clazz = (Class)e.getItem(); + try { + Layout layout = getLayoutFor(clazz, graph); + layout.setInitializer(vv.getGraphLayout()); + clusteringLayout.setDelegate(layout); + vv.setGraphLayout(clusteringLayout); + } catch(Exception ex) { + ex.printStackTrace(); + } + } + }}); + + JComboBox subLayoutTypeComboBox = new JComboBox(layoutClasses); + + subLayoutTypeComboBox.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(valueString.lastIndexOf('.')+1); + return super.getListCellRendererComponent(list, valueString, index, isSelected, + cellHasFocus); + } + }); + subLayoutTypeComboBox.addItemListener(new ItemListener() { + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + subLayoutType = (Class)e.getItem(); + } + }}); + + JComboBox subLayoutDimensionComboBox = + new JComboBox(new Dimension[]{ + new Dimension(75,75), + new Dimension(100,100), + new Dimension(150,150), + new Dimension(200,200), + new Dimension(250,250), + new Dimension(300,300) + } + ); + subLayoutDimensionComboBox.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(valueString.lastIndexOf('[')); + valueString = valueString.replaceAll("idth", ""); + valueString = valueString.replaceAll("eight",""); + return super.getListCellRendererComponent(list, valueString, index, isSelected, + cellHasFocus); + } + }); + subLayoutDimensionComboBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + subLayoutSize = (Dimension)e.getItem(); + } + }}); + subLayoutDimensionComboBox.setSelectedIndex(1); + + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog((JComponent)e.getSource(), instructions, "Help", JOptionPane.PLAIN_MESSAGE); + } + }); + Dimension space = new Dimension(20,20); + Box controls = Box.createVerticalBox(); + controls.add(Box.createRigidArea(space)); + + JPanel zoomControls = new JPanel(new GridLayout(1,2)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + heightConstrain(zoomControls); + controls.add(zoomControls); + controls.add(Box.createRigidArea(space)); + + JPanel clusterControls = new JPanel(new GridLayout(0,1)); + clusterControls.setBorder(BorderFactory.createTitledBorder("Clustering")); + clusterControls.add(cluster); + clusterControls.add(uncluster); + heightConstrain(clusterControls); + controls.add(clusterControls); + controls.add(Box.createRigidArea(space)); + + JPanel layoutControls = new JPanel(new GridLayout(0,1)); + layoutControls.setBorder(BorderFactory.createTitledBorder("Layout")); + layoutControls.add(layoutTypeComboBox); + heightConstrain(layoutControls); + controls.add(layoutControls); + + JPanel subLayoutControls = new JPanel(new GridLayout(0,1)); + subLayoutControls.setBorder(BorderFactory.createTitledBorder("SubLayout")); + subLayoutControls.add(subLayoutTypeComboBox); + subLayoutControls.add(subLayoutDimensionComboBox); + heightConstrain(subLayoutControls); + controls.add(subLayoutControls); + controls.add(Box.createRigidArea(space)); + + JPanel modePanel = new JPanel(new GridLayout(1,1)); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + heightConstrain(modePanel); + controls.add(modePanel); + controls.add(Box.createRigidArea(space)); + + controls.add(help); + controls.add(Box.createVerticalGlue()); + content.add(controls, BorderLayout.EAST); + } + + private void heightConstrain(Component component) { + Dimension d = new Dimension(component.getMaximumSize().width, + component.getMinimumSize().height); + component.setMaximumSize(d); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private Layout getLayoutFor(Class layoutClass, Graph graph) throws Exception { + Object[] args = new Object[]{graph}; + Constructor constructor = layoutClass.getConstructor(new Class[] {Graph.class}); + return constructor.newInstance(args); + } + + private void clusterPicked() { + cluster(true); + } + + private void uncluster() { + cluster(false); + } + + @SuppressWarnings("unchecked") + private void cluster(boolean state) { + if(state == true) { + // put the picked vertices into a new sublayout + Collection picked = ps.getPicked(); + if(picked.size() > 1) { + Point2D center = new Point2D.Double(); + double x = 0; + double y = 0; + for(String vertex : picked) { + Point2D p = clusteringLayout.apply(vertex); + x += p.getX(); + y += p.getY(); + } + x /= picked.size(); + y /= picked.size(); + center.setLocation(x,y); + + Graph subGraph; + try { + subGraph = graph.getClass().newInstance(); + for(String vertex : picked) { + subGraph.addVertex(vertex); + Collection incidentEdges = graph.getIncidentEdges(vertex); + for(Number edge : incidentEdges) { + Pair endpoints = graph.getEndpoints(edge); + if(picked.containsAll(endpoints)) { + // put this edge into the subgraph + subGraph.addEdge(edge, endpoints.getFirst(), endpoints.getSecond()); + } + } + } + + Layout subLayout = getLayoutFor(subLayoutType, subGraph); + subLayout.setInitializer(vv.getGraphLayout()); + subLayout.setSize(subLayoutSize); + clusteringLayout.put(subLayout,center); + vv.setGraphLayout(clusteringLayout); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } else { + // remove all sublayouts + this.clusteringLayout.removeAll(); + vv.setGraphLayout(clusteringLayout); + } + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new SubLayoutDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeCollapseDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeCollapseDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeCollapseDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeCollapseDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,384 @@ +package edu.uci.ics.jung.samples; +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ + + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToggleButton; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.subLayout.TreeCollapser; + +/** + * Demonstrates "collapsing"/"expanding" of a tree's subtrees. + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class TreeCollapseDemo extends JApplet { + + /** + * the graph + */ + Forest graph; + + Supplier> graphFactory = + new Supplier>() { + + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + + Supplier> treeFactory = + new Supplier> () { + + public Tree get() { + return new DelegateTree(graphFactory); + } + }; + + + + Supplier edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + + Supplier vertexFactory = new Supplier() { + int i=0; + public String get() { + return "V"+i++; + }}; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + VisualizationServer.Paintable rings; + + String root; + + TreeLayout layout; + FRLayout layout1; + + TreeCollapser collapser; + + RadialTreeLayout radialLayout; + + public TreeCollapseDemo() { + + // create a simple graph for the demo + graph = new DelegateForest(); + + createTree(); + + layout = new TreeLayout(graph); + collapser = new TreeCollapser(); + + radialLayout = new RadialTreeLayout(graph); + radialLayout.setSize(new Dimension(600,600)); + vv = new VisualizationViewer(layout, new Dimension(600,600)); + vv.setBackground(Color.white); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction()); + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + rings = new Rings(); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JToggleButton radial = new JToggleButton("Radial"); + radial.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + vv.setGraphLayout(radialLayout); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.addPreRenderPaintable(rings); + } else { + vv.setGraphLayout(layout); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.removePreRenderPaintable(rings); + } + vv.repaint(); + }}); + + JButton collapse = new JButton("Collapse"); + collapse.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked + = new HashSet(vv.getPickedVertexState().getPicked()); + if(picked.size() == 1) { + Object root = picked.iterator().next(); + Forest inGraph = (Forest)layout.getGraph(); + + try { + collapser.collapse(vv.getGraphLayout(), inGraph, root); + } catch (InstantiationException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JButton expand = new JButton("Expand"); + expand.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = vv.getPickedVertexState().getPicked(); + for(Object v : picked) { + if(v instanceof Forest) { + Forest inGraph + = (Forest)layout.getGraph(); + collapser.expand(inGraph, (Forest)v); + } + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(radial); + controls.add(scaleGrid); + controls.add(modeBox); + controls.add(collapse); + controls.add(expand); + content.add(controls, BorderLayout.SOUTH); + } + + class Rings implements VisualizationServer.Paintable { + + Collection depths; + + public Rings() { + depths = getDepths(); + } + + private Collection getDepths() { + Set depths = new HashSet(); + Map polarLocations = radialLayout.getPolarLocations(); + for(String v : graph.getVertices()) { + PolarPoint pp = polarLocations.get(v); + depths.add(pp.getRadius()); + } + return depths; + } + + public void paint(Graphics g) { + g.setColor(Color.lightGray); + + Graphics2D g2d = (Graphics2D)g; + Point2D center = radialLayout.getCenter(); + + Ellipse2D ellipse = new Ellipse2D.Double(); + for(double d : depths) { + ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, + center.getX()+d, center.getY()+d); + Shape shape = vv.getRenderContext(). + getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse); + g2d.draw(shape); + } + } + + public boolean useTransform() { + return true; + } + } + + /** + * + */ + private void createTree() { + graph.addVertex("V0"); + graph.addEdge(edgeFactory.get(), "V0", "V1"); + graph.addEdge(edgeFactory.get(), "V0", "V2"); + graph.addEdge(edgeFactory.get(), "V1", "V4"); + graph.addEdge(edgeFactory.get(), "V2", "V3"); + graph.addEdge(edgeFactory.get(), "V2", "V5"); + graph.addEdge(edgeFactory.get(), "V4", "V6"); + graph.addEdge(edgeFactory.get(), "V4", "V7"); + graph.addEdge(edgeFactory.get(), "V3", "V8"); + graph.addEdge(edgeFactory.get(), "V6", "V9"); + graph.addEdge(edgeFactory.get(), "V4", "V10"); + + graph.addVertex("A0"); + graph.addEdge(edgeFactory.get(), "A0", "A1"); + graph.addEdge(edgeFactory.get(), "A0", "A2"); + graph.addEdge(edgeFactory.get(), "A0", "A3"); + + graph.addVertex("B0"); + graph.addEdge(edgeFactory.get(), "B0", "B1"); + graph.addEdge(edgeFactory.get(), "B0", "B2"); + graph.addEdge(edgeFactory.get(), "B1", "B4"); + graph.addEdge(edgeFactory.get(), "B2", "B3"); + graph.addEdge(edgeFactory.get(), "B2", "B5"); + graph.addEdge(edgeFactory.get(), "B4", "B6"); + graph.addEdge(edgeFactory.get(), "B4", "B7"); + graph.addEdge(edgeFactory.get(), "B3", "B8"); + graph.addEdge(edgeFactory.get(), "B6", "B9"); + + } + + /** + * a demo class that will create a vertex shape that is either a + * polygon or star. The number of sides corresponds to the number + * of vertices that were collapsed into the vertex represented by + * this shape. + * + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexShapeFunction extends EllipseVertexShapeTransformer +{ + + ClusterVertexShapeFunction() { + setSizeTransformer(new ClusterVertexSizeFunction(20)); + } + @Override + public Shape apply(V v) { + if(v instanceof Graph) { + @SuppressWarnings("rawtypes") + int size = ((Graph)v).getVertexCount(); + if (size < 8) { + int sides = Math.max(size, 3); + return factory.getRegularPolygon(v, sides); + } + else { + return factory.getRegularStar(v, size); + } + } + return super.apply(v); + } + } + + /** + * A demo class that will make vertices larger if they represent + * a collapsed collection of original vertices + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexSizeFunction implements Function { + int size; + public ClusterVertexSizeFunction(Integer size) { + this.size = size; + } + + public Integer apply(V v) { + if(v instanceof Graph) { + return 30; + } + return size; + } + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new TreeCollapseDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeLayoutDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeLayoutDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeLayoutDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TreeLayoutDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JToggleButton; + +import com.google.common.base.Functions; +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout; +import edu.uci.ics.jung.algorithms.layout.TreeLayout; +import edu.uci.ics.jung.graph.DelegateForest; +import edu.uci.ics.jung.graph.DelegateTree; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.Tree; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse.Mode; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.util.Animator; + +/** + * Demonsrates TreeLayout and RadialTreeLayout. + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class TreeLayoutDemo extends JApplet { + + /** + * the graph + */ + Forest graph; + + Supplier> graphFactory = + new Supplier>() { + + public DirectedGraph get() { + return new DirectedSparseMultigraph(); + } + }; + + Supplier> treeFactory = + new Supplier> () { + + public Tree get() { + return new DelegateTree(graphFactory); + } + }; + + Supplier edgeFactory = new Supplier() { + int i=0; + public Integer get() { + return i++; + }}; + + Supplier vertexFactory = new Supplier() { + int i=0; + public String get() { + return "V"+i++; + }}; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + VisualizationServer.Paintable rings; + + String root; + + TreeLayout treeLayout; + + RadialTreeLayout radialLayout; + + public TreeLayoutDemo() { + + // create a simple graph for the demo + graph = new DelegateForest(); + + createTree(); + + treeLayout = new TreeLayout(graph); + radialLayout = new RadialTreeLayout(graph); + radialLayout.setSize(new Dimension(600,600)); + vv = new VisualizationViewer(treeLayout, new Dimension(600,600)); + vv.setBackground(Color.white); + vv.getRenderContext().setEdgeShapeTransformer(EdgeShape.line(graph)); + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + rings = new Rings(); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JToggleButton radial = new JToggleButton("Radial"); + radial.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + + LayoutTransition lt = + new LayoutTransition(vv, treeLayout, radialLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.addPreRenderPaintable(rings); + } else { + LayoutTransition lt = + new LayoutTransition(vv, radialLayout, treeLayout); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.removePreRenderPaintable(rings); + } + vv.repaint(); + }}); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(radial); + controls.add(scaleGrid); + controls.add(modeBox); + + content.add(controls, BorderLayout.SOUTH); + } + + class Rings implements VisualizationServer.Paintable { + + Collection depths; + + public Rings() { + depths = getDepths(); + } + + private Collection getDepths() { + Set depths = new HashSet(); + Map polarLocations = radialLayout.getPolarLocations(); + for(String v : graph.getVertices()) { + PolarPoint pp = polarLocations.get(v); + depths.add(pp.getRadius()); + } + return depths; + } + + public void paint(Graphics g) { + g.setColor(Color.lightGray); + + Graphics2D g2d = (Graphics2D)g; + Point2D center = radialLayout.getCenter(); + + Ellipse2D ellipse = new Ellipse2D.Double(); + for(double d : depths) { + ellipse.setFrameFromDiagonal(center.getX()-d, center.getY()-d, + center.getX()+d, center.getY()+d); + Shape shape = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).transform(ellipse); + g2d.draw(shape); + } + } + + public boolean useTransform() { + return true; + } + } + + /** + * + */ + private void createTree() { + graph.addVertex("V0"); + graph.addEdge(edgeFactory.get(), "V0", "V1"); + graph.addEdge(edgeFactory.get(), "V0", "V2"); + graph.addEdge(edgeFactory.get(), "V1", "V4"); + graph.addEdge(edgeFactory.get(), "V2", "V3"); + graph.addEdge(edgeFactory.get(), "V2", "V5"); + graph.addEdge(edgeFactory.get(), "V4", "V6"); + graph.addEdge(edgeFactory.get(), "V4", "V7"); + graph.addEdge(edgeFactory.get(), "V3", "V8"); + graph.addEdge(edgeFactory.get(), "V6", "V9"); + graph.addEdge(edgeFactory.get(), "V4", "V10"); + + graph.addVertex("A0"); + graph.addEdge(edgeFactory.get(), "A0", "A1"); + graph.addEdge(edgeFactory.get(), "A0", "A2"); + graph.addEdge(edgeFactory.get(), "A0", "A3"); + + graph.addVertex("B0"); + graph.addEdge(edgeFactory.get(), "B0", "B1"); + graph.addEdge(edgeFactory.get(), "B0", "B2"); + graph.addEdge(edgeFactory.get(), "B1", "B4"); + graph.addEdge(edgeFactory.get(), "B2", "B3"); + graph.addEdge(edgeFactory.get(), "B2", "B5"); + graph.addEdge(edgeFactory.get(), "B4", "B6"); + graph.addEdge(edgeFactory.get(), "B4", "B7"); + graph.addEdge(edgeFactory.get(), "B3", "B8"); + graph.addEdge(edgeFactory.get(), "B6", "B9"); + + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new TreeLayoutDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TwoModelDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TwoModelDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/TwoModelDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/TwoModelDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.ISOMLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.MultiPickedState; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Demonstrates a single graph with 2 layouts in 2 views. + * They share picking, transforms, and a pluggable renderer + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class TwoModelDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + + /** + * the visual components and renderers for the graph + */ + VisualizationViewer vv1; + VisualizationViewer vv2; + + /** + * the normal Function + */ + MutableTransformer layoutTransformer; + + Dimension preferredSize = new Dimension(300,300); + + /** + * create an instance of a simple graph in two views with controls to + * demo the zoom features. + * + */ + public TwoModelDemo() { + + // create a simple graph for the demo + // both models will share one graph + graph = TestGraphs.getOneComponentGraph(); + + // create two layouts for the one graph, one layout for each model + Layout layout1 = new FRLayout(graph); + Layout layout2 = new ISOMLayout(graph); + + // create the two models, each with a different layout + VisualizationModel vm1 = + new DefaultVisualizationModel(layout1, preferredSize); + VisualizationModel vm2 = + new DefaultVisualizationModel(layout2, preferredSize); + + // create the two views, one for each model + // they share the same renderer + vv1 = new VisualizationViewer(vm1, preferredSize); + vv2 = new VisualizationViewer(vm2, preferredSize); + vv1.setRenderContext(vv2.getRenderContext()); + + // share the model Function between the two models +// layoutTransformer = vv1.getLayoutTransformer(); +// vv2.setLayoutTransformer(layoutTransformer); +// +// // share the view Function between the two models +// vv2.setViewTransformer(vv1.getViewTransformer()); + + vv2.getRenderContext().setMultiLayerTransformer(vv1.getRenderContext().getMultiLayerTransformer()); + vv2.getRenderContext().getMultiLayerTransformer().addChangeListener(vv1); + + vv1.setBackground(Color.white); + vv2.setBackground(Color.white); + + // share one PickedState between the two views + PickedState ps = new MultiPickedState(); + vv1.setPickedVertexState(ps); + vv2.setPickedVertexState(ps); + PickedState pes = new MultiPickedState(); + vv1.setPickedEdgeState(pes); + vv2.setPickedEdgeState(pes); + + // set an edge paint function that will show picking for edges + vv1.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv1.getPickedEdgeState(), Color.black, Color.red)); + vv1.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv1.getPickedVertexState(), + Color.red, Color.yellow)); + // add default listeners for ToolTips + vv1.setVertexToolTipTransformer(new ToStringLabeller()); + vv2.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + JPanel panel = new JPanel(new GridLayout(1,0)); + panel.add(new GraphZoomScrollPane(vv1)); + panel.add(new GraphZoomScrollPane(vv2)); + + content.add(panel); + + // create a GraphMouse for each view + final DefaultModalGraphMouse gm1 + = new DefaultModalGraphMouse(); + + DefaultModalGraphMouse gm2 + = new DefaultModalGraphMouse(); + + vv1.setGraphMouse(gm1); + vv2.setGraphMouse(gm2); + + // create zoom buttons for scaling the Function that is + // shared between the two models. + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1.1f, vv1.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv1, 1/1.1f, vv1.getCenter()); + } + }); + + JPanel zoomPanel = new JPanel(new GridLayout(1,2)); + zoomPanel.setBorder(BorderFactory.createTitledBorder("Zoom")); + + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + gm1.getModeComboBox().addItemListener(gm2.getModeListener()); + modePanel.add(gm1.getModeComboBox()); + + JPanel controls = new JPanel(); + zoomPanel.add(plus); + zoomPanel.add(minus); + controls.add(zoomPanel); + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new TwoModelDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/UnicodeLabelDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/UnicodeLabelDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/UnicodeLabelDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/UnicodeLabelDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.decorators.VertexIconShapeTransformer; +import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; + +/** + * A demo that shows flag images as vertices, and uses unicode + * to render vertex labels. + * + * @author Tom Nelson + * + */ +public class UnicodeLabelDemo { + + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + boolean showLabels; + + public UnicodeLabelDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + Integer[] v = createVertices(10); + createEdges(v); + Map iconMap = new HashMap(); + + vv = new VisualizationViewer(new FRLayout(graph)); + vv.getRenderContext().setVertexLabelTransformer(new UnicodeVertexStringer(v)); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); + VertexIconShapeTransformer vertexIconShapeFunction = + new VertexIconShapeTransformer(new EllipseVertexShapeTransformer()); + Function vertexIconFunction = Functions.forMap(iconMap); + vv.getRenderContext().setVertexShapeTransformer(vertexIconShapeFunction); + vv.getRenderContext().setVertexIconTransformer(vertexIconFunction); + loadImages(v, iconMap); + vertexIconShapeFunction.setIconMap(iconMap); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.white, Color.yellow)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.lightGray)); + + vv.setBackground(Color.white); + + // add my listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + final DefaultModalGraphMouse gm + = new DefaultModalGraphMouse(); + vv.setGraphMouse(gm); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JCheckBox lo = new JCheckBox("Show Labels"); + lo.addItemListener(new ItemListener(){ + public void itemStateChanged(ItemEvent e) { + showLabels = e.getStateChange() == ItemEvent.SELECTED; + vv.repaint(); + } + }); + lo.setSelected(true); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + controls.add(lo); + controls.add(gm.getModeComboBox()); + content.add(controls, BorderLayout.SOUTH); + + frame.pack(); + frame.setVisible(true); + } + + + class UnicodeVertexStringer implements Function { + + Map map = new HashMap(); + Map iconMap = new HashMap(); + String[] labels = { + "\u0057\u0065\u006C\u0063\u006F\u006D\u0065\u0020\u0074\u006F\u0020JUNG\u0021", + "\u6B22\u8FCE\u4F7F\u7528\u0020\u0020JUNG\u0021", + "\u0414\u043E\u0431\u0440\u043E\u0020\u043F\u043E\u0436\u0430\u043B\u043E\u0432\u0430\u0422\u044A\u0020\u0432\u0020JUNG\u0021", + "\u0042\u0069\u0065\u006E\u0076\u0065\u006E\u0075\u0065\u0020\u0061\u0075\u0020JUNG\u0021", + "\u0057\u0069\u006C\u006B\u006F\u006D\u006D\u0065\u006E\u0020\u007A\u0075\u0020JUNG\u0021", + "JUNG\u3078\u3087\u3045\u3053\u305D\u0021", +// "\u0053\u00E9\u006A\u0061\u0020\u0042\u0065\u006D\u0076\u0069\u006E\u0064\u006F\u0020JUNG\u0021", + "\u0042\u0069\u0065\u006E\u0076\u0065\u006E\u0069\u0064\u0061\u0020\u0061\u0020JUNG\u0021" + }; + + public UnicodeVertexStringer(V[] vertices) { + for(int i=0; i imageMap) { + + ImageIcon[] icons = null; + try { + icons = new ImageIcon[] { + new ImageIcon(getClass().getResource("/images/united-states.gif")), + new ImageIcon(getClass().getResource("/images/china.gif")), + new ImageIcon(getClass().getResource("/images/russia.gif")), + new ImageIcon(getClass().getResource("/images/france.gif")), + new ImageIcon(getClass().getResource("/images/germany.gif")), + new ImageIcon(getClass().getResource("/images/japan.gif")), + new ImageIcon(getClass().getResource("/images/spain.gif")) + }; + } catch(Exception ex) { + System.err.println("You need flags.jar in your classpath to see the flag icons."); + } + for(int i=0; icons != null && i} for the collapsed vertices. + * + * @author Tom Nelson + * + */ +@SuppressWarnings({"serial", "rawtypes", "unchecked"}) +public class VertexCollapseDemo extends JApplet { + + String instructions = + "Use the mouse to select multiple vertices"+ + "

        either by dragging a region, or by shift-clicking"+ + "

        on multiple vertices."+ + "

        After you select vertices, use the Collapse button"+ + "

        to combine them into a single vertex."+ + "

        Select a 'collapsed' vertex and use the Expand button"+ + "

        to restore the collapsed vertices."+ + "

        The Restore button will restore the original graph."+ + "

        If you select 2 (and only 2) vertices, then press"+ + "

        the Compress Edges button, parallel edges between"+ + "

        those two vertices will no longer be expanded."+ + "

        If you select 2 (and only 2) vertices, then press"+ + "

        the Expand Edges button, parallel edges between"+ + "

        those two vertices will be expanded."+ + "

        You can drag the vertices with the mouse." + + "

        Use the 'Picking'/'Transforming' combo-box to switch"+ + "

        between picking and transforming mode."; + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + Layout layout; + + GraphCollapser collapser; + + public VertexCollapseDemo() { + + // create a simple graph for the demo + graph = + TestGraphs.getOneComponentGraph(); + collapser = new GraphCollapser(graph); + + layout = new FRLayout(graph); + + Dimension preferredSize = new Dimension(400,400); + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(layout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction()); + + final PredicatedParallelEdgeIndexFunction eif = PredicatedParallelEdgeIndexFunction.getInstance(); + final Set exclusions = new HashSet(); + eif.setPredicate(new Predicate() { + + public boolean apply(Object e) { + + return exclusions.contains(e); + }}); + + + vv.getRenderContext().setParallelEdgeIndexFunction(eif); + + vv.setBackground(Color.white); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller() { + + @Override + public String apply(Object v) { + if(v instanceof Graph) { + return ((Graph)v).getVertices().toString(); + } + return super.apply(v); + }}); + + /** + * the regular graph mouse for the normal view + */ + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.PICKING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton collapse = new JButton("Collapse"); + collapse.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = new HashSet(vv.getPickedVertexState().getPicked()); + if(picked.size() > 1) { + Graph inGraph = layout.getGraph(); + Graph clusterGraph = collapser.getClusterGraph(inGraph, picked); + + Graph g = collapser.collapse(layout.getGraph(), clusterGraph); + double sumx = 0; + double sumy = 0; + for(Object v : picked) { + Point2D p = (Point2D)layout.apply(v); + sumx += p.getX(); + sumy += p.getY(); + } + Point2D cp = new Point2D.Double(sumx/picked.size(), sumy/picked.size()); + vv.getRenderContext().getParallelEdgeIndexFunction().reset(); + layout.setGraph(g); + layout.setLocation(clusterGraph, cp); + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JButton compressEdges = new JButton("Compress Edges"); + compressEdges.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = vv.getPickedVertexState().getPicked(); + if(picked.size() == 2) { + Pair pair = new Pair(picked); + Graph graph = layout.getGraph(); + Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst())); + edges.retainAll(graph.getIncidentEdges(pair.getSecond())); + exclusions.addAll(edges); + vv.repaint(); + } + + }}); + + JButton expandEdges = new JButton("Expand Edges"); + expandEdges.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = vv.getPickedVertexState().getPicked(); + if(picked.size() == 2) { + Pair pair = new Pair(picked); + Graph graph = layout.getGraph(); + Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst())); + edges.retainAll(graph.getIncidentEdges(pair.getSecond())); + exclusions.removeAll(edges); + vv.repaint(); + } + + }}); + + JButton expand = new JButton("Expand"); + expand.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = new HashSet(vv.getPickedVertexState().getPicked()); + for(Object v : picked) { + if(v instanceof Graph) { + + Graph g = collapser.expand(layout.getGraph(), (Graph)v); + vv.getRenderContext().getParallelEdgeIndexFunction().reset(); + layout.setGraph(g); + } + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JButton reset = new JButton("Reset"); + reset.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + layout.setGraph(graph); + exclusions.clear(); + vv.repaint(); + }}); + + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog((JComponent)e.getSource(), instructions, "Help", JOptionPane.PLAIN_MESSAGE); + } + }); + + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + controls.add(zoomControls); + JPanel collapseControls = new JPanel(new GridLayout(3,1)); + collapseControls.setBorder(BorderFactory.createTitledBorder("Picked")); + collapseControls.add(collapse); + collapseControls.add(expand); + collapseControls.add(compressEdges); + collapseControls.add(expandEdges); + collapseControls.add(reset); + controls.add(collapseControls); + controls.add(modeBox); + controls.add(help); + content.add(controls, BorderLayout.SOUTH); + } + + /** + * a demo class that will create a vertex shape that is either a + * polygon or star. The number of sides corresponds to the number + * of vertices that were collapsed into the vertex represented by + * this shape. + * + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexShapeFunction extends EllipseVertexShapeTransformer { + + ClusterVertexShapeFunction() { + setSizeTransformer(new ClusterVertexSizeFunction(20)); + } + @Override + public Shape apply(V v) { + if(v instanceof Graph) { + int size = ((Graph)v).getVertexCount(); + if (size < 8) { + int sides = Math.max(size, 3); + return factory.getRegularPolygon(v, sides); + } + else { + return factory.getRegularStar(v, size); + } + } + return super.apply(v); + } + } + + /** + * A demo class that will make vertices larger if they represent + * a collapsed collection of original vertices + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexSizeFunction implements Function { + int size; + public ClusterVertexSizeFunction(Integer size) { + this.size = size; + } + + public Integer apply(V v) { + if(v instanceof Graph) { + return 30; + } + return size; + } + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new VertexCollapseDemo()); + f.pack(); + f.setVisible(true); + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexCollapseDemoWithLayouts.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.Point2D; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.ISOMLayout; +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout; +import edu.uci.ics.jung.algorithms.layout.SpringLayout2; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.layout.LayoutTransition; +import edu.uci.ics.jung.visualization.subLayout.GraphCollapser; +import edu.uci.ics.jung.visualization.util.Animator; +import edu.uci.ics.jung.visualization.util.PredicatedParallelEdgeIndexFunction; + + +/** + * A demo that shows how collections of vertices can be collapsed + * into a single vertex. In this demo, the vertices that are + * collapsed are those mouse-picked by the user. Any criteria + * could be used to form the vertex collections to be collapsed, + * perhaps some common characteristic of those vertex objects. + * + * Note that the collection types don't use generics in this + * demo, because the vertices are of two types: String for plain + * vertices, and {@code Graph} for the collapsed vertices. + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class VertexCollapseDemoWithLayouts extends JApplet { + + String instructions = + "Use the mouse to select multiple vertices"+ + "

        either by dragging a region, or by shift-clicking"+ + "

        on multiple vertices."+ + "

        After you select vertices, use the Collapse button"+ + "

        to combine them into a single vertex."+ + "

        Select a 'collapsed' vertex and use the Expand button"+ + "

        to restore the collapsed vertices."+ + "

        The Restore button will restore the original graph."+ + "

        If you select 2 (and only 2) vertices, then press"+ + "

        the Compress Edges button, parallel edges between"+ + "

        those two vertices will no longer be expanded."+ + "

        If you select 2 (and only 2) vertices, then press"+ + "

        the Expand Edges button, parallel edges between"+ + "

        those two vertices will be expanded."+ + "

        You can drag the vertices with the mouse." + + "

        Use the 'Picking'/'Transforming' combo-box to switch"+ + "

        between picking and transforming mode."; + /** + * the graph + */ + @SuppressWarnings("rawtypes") + Graph graph; + @SuppressWarnings("rawtypes") + Graph collapsedGraph; + + /** + * the visual component and renderer for the graph + */ + @SuppressWarnings("rawtypes") + VisualizationViewer vv; + + @SuppressWarnings("rawtypes") + Layout layout; + + GraphCollapser collapser; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public VertexCollapseDemoWithLayouts() { + + // create a simple graph for the demo + graph = + TestGraphs.getOneComponentGraph(); + collapsedGraph = graph; + collapser = new GraphCollapser(graph); + + layout = new FRLayout(graph); + + Dimension preferredSize = new Dimension(400,400); + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(layout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + vv.getRenderContext().setVertexShapeTransformer(new ClusterVertexShapeFunction()); + + final PredicatedParallelEdgeIndexFunction eif = PredicatedParallelEdgeIndexFunction.getInstance(); + final Set exclusions = new HashSet(); + eif.setPredicate(new Predicate() { + + public boolean apply(Object e) { + + return exclusions.contains(e); + }}); + + + vv.getRenderContext().setParallelEdgeIndexFunction(eif); + + vv.setBackground(Color.white); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller() { + + /* (non-Javadoc) + * @see edu.uci.ics.jung.visualization.decorators.DefaultToolTipFunction#getToolTipText(java.lang.Object) + */ + @Override + public String apply(Object v) { + if(v instanceof Graph) { + return ((Graph)v).getVertices().toString(); + } + return super.apply(v); + }}); + + /** + * the regular graph mouse for the normal view + */ + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.PICKING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton collapse = new JButton("Collapse"); + collapse.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = new HashSet(vv.getPickedVertexState().getPicked()); + if(picked.size() > 1) { + Graph inGraph = layout.getGraph(); + Graph clusterGraph = collapser.getClusterGraph(inGraph, picked); + + Graph g = collapser.collapse(layout.getGraph(), clusterGraph); + collapsedGraph = g; + double sumx = 0; + double sumy = 0; + for(Object v : picked) { + Point2D p = (Point2D)layout.apply(v); + sumx += p.getX(); + sumy += p.getY(); + } + Point2D cp = new Point2D.Double(sumx/picked.size(), sumy/picked.size()); + vv.getRenderContext().getParallelEdgeIndexFunction().reset(); + layout.setGraph(g); + layout.setLocation(clusterGraph, cp); + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JButton compressEdges = new JButton("Compress Edges"); + compressEdges.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = vv.getPickedVertexState().getPicked(); + if(picked.size() == 2) { + Pair pair = new Pair(picked); + Graph graph = layout.getGraph(); + Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst())); + edges.retainAll(graph.getIncidentEdges(pair.getSecond())); + exclusions.addAll(edges); + vv.repaint(); + } + + }}); + + JButton expandEdges = new JButton("Expand Edges"); + expandEdges.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = vv.getPickedVertexState().getPicked(); + if(picked.size() == 2) { + Pair pair = new Pair(picked); + Graph graph = layout.getGraph(); + Collection edges = new HashSet(graph.getIncidentEdges(pair.getFirst())); + edges.retainAll(graph.getIncidentEdges(pair.getSecond())); + exclusions.removeAll(edges); + vv.repaint(); + } + + }}); + + JButton expand = new JButton("Expand"); + expand.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Collection picked = new HashSet(vv.getPickedVertexState().getPicked()); + for(Object v : picked) { + if(v instanceof Graph) { + + Graph g = collapser.expand(layout.getGraph(), (Graph)v); + vv.getRenderContext().getParallelEdgeIndexFunction().reset(); + layout.setGraph(g); + } + vv.getPickedVertexState().clear(); + vv.repaint(); + } + }}); + + JButton reset = new JButton("Reset"); + reset.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + layout.setGraph(graph); + exclusions.clear(); + vv.repaint(); + }}); + + JButton help = new JButton("Help"); + help.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JOptionPane.showMessageDialog((JComponent)e.getSource(), instructions, "Help", JOptionPane.PLAIN_MESSAGE); + } + }); + Class[] combos = getCombos(); + final JComboBox jcb = new JComboBox(combos); + // use a renderer to shorten the layout name presentation + jcb.setRenderer(new DefaultListCellRenderer() { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(valueString.lastIndexOf('.')+1); + return super.getListCellRendererComponent(list, valueString, index, isSelected, + cellHasFocus); + } + }); + jcb.addActionListener(new LayoutChooser(jcb, vv)); + jcb.setSelectedItem(FRLayout.class); + + + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + controls.add(zoomControls); + JPanel collapseControls = new JPanel(new GridLayout(3,1)); + collapseControls.setBorder(BorderFactory.createTitledBorder("Picked")); + collapseControls.add(collapse); + collapseControls.add(expand); + collapseControls.add(compressEdges); + collapseControls.add(expandEdges); + collapseControls.add(reset); + controls.add(collapseControls); + controls.add(modeBox); + controls.add(help); + controls.add(jcb); + content.add(controls, BorderLayout.SOUTH); + } + + /** + * a demo class that will create a vertex shape that is either a + * polygon or star. The number of sides corresponds to the number + * of vertices that were collapsed into the vertex represented by + * this shape. + * + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexShapeFunction extends EllipseVertexShapeTransformer { + + ClusterVertexShapeFunction() { + setSizeTransformer(new ClusterVertexSizeFunction(20)); + } + @Override + public Shape apply(V v) { + if(v instanceof Graph) { + @SuppressWarnings("rawtypes") + int size = ((Graph)v).getVertexCount(); + if (size < 8) { + int sides = Math.max(size, 3); + return factory.getRegularPolygon(v, sides); + } + else { + return factory.getRegularStar(v, size); + } + } + return super.apply(v); + } + } + + /** + * A demo class that will make vertices larger if they represent + * a collapsed collection of original vertices + * @author Tom Nelson + * + * @param the vertex type + */ + class ClusterVertexSizeFunction implements Function { + int size; + public ClusterVertexSizeFunction(Integer size) { + this.size = size; + } + + public Integer apply(V v) { + if(v instanceof Graph) { + return 30; + } + return size; + } + } + + private class LayoutChooser implements ActionListener + { + private final JComboBox jcb; + @SuppressWarnings("rawtypes") + private final VisualizationViewer vv; + + private LayoutChooser(JComboBox jcb, VisualizationViewer vv) + { + super(); + this.jcb = jcb; + this.vv = vv; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void actionPerformed(ActionEvent arg0) + { + Object[] constructorArgs = + { collapsedGraph }; + + Class layoutC = + (Class) jcb.getSelectedItem(); + try + { + Constructor constructor = layoutC + .getConstructor(new Class[] {Graph.class}); + Object o = constructor.newInstance(constructorArgs); + Layout l = (Layout) o; + l.setInitializer(vv.getGraphLayout()); + l.setSize(vv.getSize()); + layout = l; + LayoutTransition lt = + new LayoutTransition(vv, vv.getGraphLayout(), l); + Animator animator = new Animator(lt); + animator.start(); + vv.getRenderContext().getMultiLayerTransformer().setToIdentity(); + vv.repaint(); + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + /** + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + private Class[] getCombos() + { + List> layouts = new ArrayList>(); + layouts.add(KKLayout.class); + layouts.add(FRLayout.class); + layouts.add(CircleLayout.class); + layouts.add(SpringLayout.class); + layouts.add(SpringLayout2.class); + layouts.add(ISOMLayout.class); + return layouts.toArray(new Class[0]); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new VertexCollapseDemoWithLayouts()); + f.pack(); + f.setVisible(true); + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexImageShaperDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexImageShaperDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexImageShaperDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexImageShaperDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.util.RandomLocationTransformer; +import edu.uci.ics.jung.graph.DirectedSparseGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.LayeredIcon; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.decorators.VertexIconShapeTransformer; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Checkmark; +import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; +import edu.uci.ics.jung.visualization.util.ImageShapeUtils; + +/** + * Demonstrates the use of images to represent graph vertices. + * The images are supplied via the VertexShapeFunction so that + * both the image and its shape can be utilized. + * + * The images used in this demo (courtesy of slashdot.org) are + * rectangular but with a transparent background. When vertices + * are represented by these images, it looks better if the actual + * shape of the opaque part of the image is computed so that the + * edge arrowheads follow the visual shape of the image. This demo + * uses the FourPassImageShaper class to compute the Shape from + * an image with transparent background. + * + * @author Tom Nelson + * + */ +public class VertexImageShaperDemo extends JApplet { + + /** + * + */ + private static final long serialVersionUID = -4332663871914930864L; + + private static final int VERTEX_COUNT=11; + + /** + * the graph + */ + DirectedSparseGraph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + /** + * some icon names to use + */ + String[] iconNames = { + "apple", + "os", + "x", + "linux", + "inputdevices", + "wireless", + "graphics3", + "gamespcgames", + "humor", + "music", + "privacy" + }; + + public VertexImageShaperDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseGraph(); + createGraph(VERTEX_COUNT); + + // a Map for the labels + Map map = new HashMap(); + for(int i=0; i iconMap = new HashMap(); + for(int i=0; i layout = new FRLayout(graph); + layout.setMaxIterations(100); + layout.setInitializer(new RandomLocationTransformer(new Dimension(400,400), 0)); + vv = new VisualizationViewer(layout, new Dimension(400,400)); + + // This demo uses a special renderer to turn outlines on and off. + // you do not need to do this in a real application. + // Instead, just let vv use the Renderer it already has + vv.getRenderer().setVertexRenderer(new DemoRenderer()); + + Function vpf = + new PickableVertexPaintTransformer(vv.getPickedVertexState(), Color.white, Color.yellow); + vv.getRenderContext().setVertexFillPaintTransformer(vpf); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(vv.getPickedEdgeState(), Color.black, Color.cyan)); + + vv.setBackground(Color.white); + + + final Function vertexStringerImpl = + new VertexStringerImpl(map); + vv.getRenderContext().setVertexLabelTransformer(vertexStringerImpl); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.cyan)); + vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan)); +// vv.getRenderContext().setEdgeLabelTransformer(new Function() { +// URL url = getClass().getResource("/images/lightning-s.gif"); +// public String transform(Number input) { +// +// return ""+input.toString(); +// }}); + + // For this demo only, I use a special class that lets me turn various + // features on and off. For a real application, use VertexIconShapeTransformer instead. + final DemoVertexIconShapeTransformer vertexIconShapeTransformer = + new DemoVertexIconShapeTransformer(new EllipseVertexShapeTransformer()); + vertexIconShapeTransformer.setIconMap(iconMap); + + final DemoVertexIconTransformer vertexIconTransformer + = new DemoVertexIconTransformer(iconMap); + + vv.getRenderContext().setVertexShapeTransformer(vertexIconShapeTransformer); + vv.getRenderContext().setVertexIconTransformer(vertexIconTransformer); + + // un-comment for RStar Tree visual testing + //vv.addPostRenderPaintable(new BoundingRectanglePaintable(vv.getRenderContext(), vv.getGraphLayout())); + + // Get the pickedState and add a listener that will decorate the + // Vertex images with a checkmark icon when they are picked + PickedState ps = vv.getPickedVertexState(); + ps.addItemListener(new PickWithIconListener(vertexIconTransformer)); + + vv.addPostRenderPaintable(new VisualizationViewer.Paintable(){ + int x; + int y; + Font font; + FontMetrics metrics; + int swidth; + int sheight; + String str = "Thank You, slashdot.org, for the images!"; + + public void paint(Graphics g) { + Dimension d = vv.getSize(); + if(font == null) { + font = new Font(g.getFont().getName(), Font.BOLD, 20); + metrics = g.getFontMetrics(font); + swidth = metrics.stringWidth(str); + sheight = metrics.getMaxAscent()+metrics.getMaxDescent(); + x = (d.width-swidth)/2; + y = (int)(d.height-sheight*1.5); + } + g.setFont(font); + Color oldColor = g.getColor(); + g.setColor(Color.lightGray); + g.drawString(str, x, y); + g.setColor(oldColor); + } + public boolean useTransform() { + return false; + } + }); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + content.add(panel); + + final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JCheckBox shape = new JCheckBox("Shape"); + shape.addItemListener(new ItemListener(){ + + public void itemStateChanged(ItemEvent e) { + vertexIconShapeTransformer.setShapeImages(e.getStateChange()==ItemEvent.SELECTED); + vv.repaint(); + } + }); + shape.setSelected(true); + + JCheckBox fill = new JCheckBox("Fill"); + fill.addItemListener(new ItemListener(){ + + public void itemStateChanged(ItemEvent e) { + vertexIconTransformer.setFillImages(e.getStateChange()==ItemEvent.SELECTED); + vv.repaint(); + } + }); + fill.setSelected(true); + + JCheckBox drawOutlines = new JCheckBox("Outline"); + drawOutlines.addItemListener(new ItemListener(){ + + public void itemStateChanged(ItemEvent e) { + vertexIconTransformer.setOutlineImages(e.getStateChange()==ItemEvent.SELECTED); + vv.repaint(); + } + }); + + JComboBox modeBox = graphMouse.getModeComboBox(); + JPanel modePanel = new JPanel(); + modePanel.setBorder(BorderFactory.createTitledBorder("Mouse Mode")); + modePanel.add(modeBox); + + JPanel scaleGrid = new JPanel(new GridLayout(1,0)); + scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom")); + JPanel labelFeatures = new JPanel(new GridLayout(1,0)); + labelFeatures.setBorder(BorderFactory.createTitledBorder("Image Effects")); + JPanel controls = new JPanel(); + scaleGrid.add(plus); + scaleGrid.add(minus); + controls.add(scaleGrid); + labelFeatures.add(shape); + labelFeatures.add(fill); + labelFeatures.add(drawOutlines); + + controls.add(labelFeatures); + controls.add(modePanel); + content.add(controls, BorderLayout.SOUTH); + } + + /** + * When Vertices are picked, add a checkmark icon to the imager. + * Remove the icon when a Vertex is unpicked + * @author Tom Nelson + * + */ + public static class PickWithIconListener implements ItemListener { + Function imager; + Icon checked; + + public PickWithIconListener(Function imager) { + this.imager = imager; + checked = new Checkmark(); + } + + public void itemStateChanged(ItemEvent e) { + @SuppressWarnings("unchecked") + Icon icon = imager.apply((V)e.getItem()); + if(icon != null && icon instanceof LayeredIcon) { + if(e.getStateChange() == ItemEvent.SELECTED) { + ((LayeredIcon)icon).add(checked); + } else { + ((LayeredIcon)icon).remove(checked); + } + } + } + } + /** + * A simple implementation of VertexStringer that + * gets Vertex labels from a Map + * + * @author Tom Nelson + * + * + */ + public static class VertexStringerImpl implements Function { + + Map map = new HashMap(); + + boolean enabled = true; + + public VertexStringerImpl(Map map) { + this.map = map; + } + + /* (non-Javadoc) + * @see edu.uci.ics.jung.graph.decorators.VertexStringer#getLabel(edu.uci.ics.jung.graph.Vertex) + */ + public String apply(V v) { + if(isEnabled()) { + return map.get(v); + } else { + return ""; + } + } + + /** + * @return Returns the enabled. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * @param enabled The enabled to set. + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private void createGraph(int vertexCount) { + for (int i = 0; i < vertexCount; i++) { + graph.addVertex(i); + } + int j=0; + graph.addEdge(j++, 0, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 3, 0, EdgeType.DIRECTED); + graph.addEdge(j++, 0, 4, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 5, 3, EdgeType.DIRECTED); + graph.addEdge(j++, 2, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 1, EdgeType.DIRECTED); + graph.addEdge(j++, 8, 2, EdgeType.DIRECTED); + graph.addEdge(j++, 3, 8, EdgeType.DIRECTED); + graph.addEdge(j++, 6, 7, EdgeType.DIRECTED); + graph.addEdge(j++, 7, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 0, 9, EdgeType.DIRECTED); + graph.addEdge(j++, 9, 8, EdgeType.DIRECTED); + graph.addEdge(j++, 7, 6, EdgeType.DIRECTED); + graph.addEdge(j++, 6, 5, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 2, EdgeType.DIRECTED); + graph.addEdge(j++, 5, 4, EdgeType.DIRECTED); + graph.addEdge(j++, 4, 10, EdgeType.DIRECTED); + graph.addEdge(j++, 10, 4, EdgeType.DIRECTED); + } + + /** + * This class exists only to provide settings to turn on/off shapes and image fill + * in this demo. + * + *

        For a real application, just use {@code Functions.forMap(iconMap)} to provide a + * {@code Function}. + */ + public static class DemoVertexIconTransformer implements Function { + boolean fillImages = true; + boolean outlineImages = false; + Map iconMap = new HashMap(); + + public DemoVertexIconTransformer(Map iconMap) { + this.iconMap = iconMap; + } + + /** + * @return Returns the fillImages. + */ + public boolean isFillImages() { + return fillImages; + } + /** + * @param fillImages The fillImages to set. + */ + public void setFillImages(boolean fillImages) { + this.fillImages = fillImages; + } + + public boolean isOutlineImages() { + return outlineImages; + } + public void setOutlineImages(boolean outlineImages) { + this.outlineImages = outlineImages; + } + + public Icon apply(V v) { + if(fillImages) { + return (Icon)iconMap.get(v); + } else { + return null; + } + } + } + + /** + * this class exists only to provide settings to turn on/off shapes and image fill + * in this demo. + * In a real application, use VertexIconShapeTransformer instead. + * + */ + public static class DemoVertexIconShapeTransformer extends VertexIconShapeTransformer { + + boolean shapeImages = true; + + public DemoVertexIconShapeTransformer(Function delegate) { + super(delegate); + } + + /** + * @return Returns the shapeImages. + */ + public boolean isShapeImages() { + return shapeImages; + } + /** + * @param shapeImages The shapeImages to set. + */ + public void setShapeImages(boolean shapeImages) { + shapeMap.clear(); + this.shapeImages = shapeImages; + } + + public Shape transform(V v) { + Icon icon = (Icon) iconMap.get(v); + + if (icon != null && icon instanceof ImageIcon) { + + Image image = ((ImageIcon) icon).getImage(); + + Shape shape = shapeMap.get(image); + if (shape == null) { + if (shapeImages) { + shape = ImageShapeUtils.getShape(image, 30); + } else { + shape = new Rectangle2D.Float(0, 0, + image.getWidth(null), image.getHeight(null)); + } + if(shape.getBounds().getWidth() > 0 && + shape.getBounds().getHeight() > 0) { + int width = image.getWidth(null); + int height = image.getHeight(null); + AffineTransform transform = + AffineTransform.getTranslateInstance(-width / 2, -height / 2); + shape = transform.createTransformedShape(shape); + shapeMap.put(image, shape); + } + } + return shape; + } else { + return delegate.apply(v); + } + } + } + + /** + * a special renderer that can turn outlines on and off + * in this demo. + * You won't need this for a real application. + * Use BasicVertexRenderer instead + * + * @author Tom Nelson + * + */ + class DemoRenderer extends BasicVertexRenderer { +// public void paintIconForVertex(RenderContext rc, V v, Layout layout) { +// +// Point2D p = layout.transform(v); +// p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); +// float x = (float)p.getX(); +// float y = (float)p.getY(); +// +// GraphicsDecorator g = rc.getGraphicsContext(); +// boolean outlineImages = false; +// Function vertexIconFunction = rc.getVertexIconTransformer(); +// +// if(vertexIconFunction instanceof DemoVertexIconTransformer) { +// outlineImages = ((DemoVertexIconTransformer)vertexIconFunction).isOutlineImages(); +// } +// Icon icon = vertexIconFunction.transform(v); +// if(icon == null || outlineImages) { +// +// Shape s = AffineTransform.getTranslateInstance(x,y). +// createTransformedShape(rc.getVertexShapeTransformer().transform(v)); +// paintShapeForVertex(rc, v, s); +// } +// if(icon != null) { +// int xLoc = (int) (x - icon.getIconWidth()/2); +// int yLoc = (int) (y - icon.getIconHeight()/2); +// icon.paintIcon(rc.getScreenDevice(), g.getDelegate(), xLoc, yLoc); +// } +// } + } + + public static void main(String[] args) { + JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + content.add(new VertexImageShaperDemo()); + frame.pack(); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelAsShapeDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Paint; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.DefaultVertexLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.VertexLabelAsShapeRenderer; + + +/** + * This demo shows how to use the vertex labels themselves as + * the vertex shapes. Additionally, it shows html labels + * so they are multi-line, and gradient painting of the + * vertex labels. + * + * @author Tom Nelson + * + */ +public class VertexLabelAsShapeDemo extends JApplet { + + /** + * + */ + private static final long serialVersionUID = 1017336668368978842L; + + Graph graph; + + VisualizationViewer vv; + + Layout layout; + + /** + * create an instance of a simple graph with basic controls + */ + public VertexLabelAsShapeDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + layout = new FRLayout(graph); + + Dimension preferredSize = new Dimension(400,400); + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(layout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + // this class will provide both label drawing and vertex shapes + VertexLabelAsShapeRenderer vlasr = new VertexLabelAsShapeRenderer(vv.getRenderContext()); + + // customize the render context + vv.getRenderContext().setVertexLabelTransformer( + // this chains together Functions so that the html tags + // are prepended to the toString method output + Functions.compose( + new Function(){ + public String apply(String input) { + return "

        Vertex

        "+input; + }}, new ToStringLabeller())); + vv.getRenderContext().setVertexShapeTransformer(vlasr); + vv.getRenderContext().setVertexLabelRenderer(new DefaultVertexLabelRenderer(Color.red)); + vv.getRenderContext().setEdgeDrawPaintTransformer(Functions.constant(Color.yellow)); + vv.getRenderContext().setEdgeStrokeTransformer(Functions.constant(new BasicStroke(2.5f))); + + // customize the renderer + vv.getRenderer().setVertexRenderer(new GradientVertexRenderer(Color.gray, Color.white, true)); + vv.getRenderer().setVertexLabelRenderer(vlasr); + + vv.setBackground(Color.black); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + final DefaultModalGraphMouse graphMouse = + new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + JComboBox modeBox = graphMouse.getModeComboBox(); + modeBox.addItemListener(graphMouse.getModeListener()); + graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + controls.add(zoomControls); + controls.add(modeBox); + content.add(controls, BorderLayout.SOUTH); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new VertexLabelAsShapeDemo()); + f.pack(); + f.setVisible(true); + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelPositionDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelPositionDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelPositionDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VertexLabelPositionDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JPanel; + +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.TestGraphs; +import edu.uci.ics.jung.visualization.DefaultVisualizationModel; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.VisualizationModel; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position; + +/** + * Demonstrates vertex label positioning + * controlled by the user. + * In the AUTO setting, labels are placed according to + * which quadrant the vertex is in + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class VertexLabelPositionDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + + FRLayout graphLayout; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + ScalingControl scaler; + + /** + * create an instance of a simple graph with controls to + * demo the zoomand hyperbolic features. + * + */ + public VertexLabelPositionDemo() { + + // create a simple graph for the demo + graph = TestGraphs.getOneComponentGraph(); + + graphLayout = new FRLayout(graph); + graphLayout.setMaxIterations(1000); + + Dimension preferredSize = new Dimension(600,600); + + final VisualizationModel visualizationModel = + new DefaultVisualizationModel(graphLayout, preferredSize); + vv = new VisualizationViewer(visualizationModel, preferredSize); + + PickedState ps = vv.getPickedVertexState(); + PickedState pes = vv.getPickedEdgeState(); + vv.getRenderContext().setVertexFillPaintTransformer(new PickableVertexPaintTransformer(ps, Color.red, Color.yellow)); + vv.getRenderContext().setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(pes, Color.black, Color.cyan)); + vv.setBackground(Color.white); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.W); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + + // add a listener for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + + Container content = getContentPane(); + GraphZoomScrollPane gzsp = new GraphZoomScrollPane(vv); + content.add(gzsp); + + /** + * the regular graph mouse for the normal view + */ + final DefaultModalGraphMouse graphMouse + = new DefaultModalGraphMouse(); + + vv.setGraphMouse(graphMouse); + vv.addKeyListener(graphMouse.getModeKeyListener()); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + JPanel positionPanel = new JPanel(); + positionPanel.setBorder(BorderFactory.createTitledBorder("Label Position")); + JMenuBar menubar = new JMenuBar(); + menubar.add(graphMouse.getModeMenu()); + gzsp.setCorner(menubar); + JComboBox cb = new JComboBox(); + cb.addItem(Renderer.VertexLabel.Position.N); + cb.addItem(Renderer.VertexLabel.Position.NE); + cb.addItem(Renderer.VertexLabel.Position.E); + cb.addItem(Renderer.VertexLabel.Position.SE); + cb.addItem(Renderer.VertexLabel.Position.S); + cb.addItem(Renderer.VertexLabel.Position.SW); + cb.addItem(Renderer.VertexLabel.Position.W); + cb.addItem(Renderer.VertexLabel.Position.NW); + cb.addItem(Renderer.VertexLabel.Position.N); + cb.addItem(Renderer.VertexLabel.Position.CNTR); + cb.addItem(Renderer.VertexLabel.Position.AUTO); + cb.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + Renderer.VertexLabel.Position position = + (Renderer.VertexLabel.Position)e.getItem(); + vv.getRenderer().getVertexLabelRenderer().setPosition(position); + vv.repaint(); + }}); + cb.setSelectedItem(Renderer.VertexLabel.Position.SE); + positionPanel.add(cb); + JPanel controls = new JPanel(); + JPanel zoomControls = new JPanel(new GridLayout(2,1)); + zoomControls.setBorder(BorderFactory.createTitledBorder("Zoom")); + zoomControls.add(plus); + zoomControls.add(minus); + + controls.add(zoomControls); + controls.add(positionPanel); + content.add(controls, BorderLayout.SOUTH); + } + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(new VertexLabelPositionDemo()); + f.pack(); + f.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VisualizationImageServerDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VisualizationImageServerDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/VisualizationImageServerDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/VisualizationImageServerDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Paint; +import java.awt.geom.Point2D; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; + +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.KKLayout; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.VisualizationImageServer; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner; + + +/** + * Demonstrates VisualizationImageServer. + * @author Tom Nelson + * + */ +public class VisualizationImageServerDemo { + + /** + * the graph + */ + DirectedSparseMultigraph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationImageServer vv; + + /** + * + */ + public VisualizationImageServerDemo() { + + // create a simple graph for the demo + graph = new DirectedSparseMultigraph(); + String[] v = createVertices(10); + createEdges(v); + + vv = new VisualizationImageServer(new KKLayout(graph), new Dimension(600,600)); + + vv.getRenderer().setVertexRenderer( + new GradientVertexRenderer( + Color.white, Color.red, + Color.white, Color.blue, + vv.getPickedVertexState(), + false)); + vv.getRenderContext().setEdgeDrawPaintTransformer(Functions.constant(Color.lightGray)); + vv.getRenderContext().setArrowFillPaintTransformer(Functions.constant(Color.lightGray)); + vv.getRenderContext().setArrowDrawPaintTransformer(Functions.constant(Color.lightGray)); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner()); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO); + + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + Image im = vv.getImage(new Point2D.Double(300,300), new Dimension(600,600)); + Icon icon = new ImageIcon(im); + JLabel label = new JLabel(icon); + content.add(label); + frame.pack(); + frame.setVisible(true); + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private String[] createVertices(int count) { + String[] v = new String[count]; + for (int i = 0; i < count; i++) { + v[i] = "V"+i; + graph.addVertex(v[i]); + } + return v; + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges(String[] v) { + graph.addEdge(new Double(Math.random()), v[0], v[1], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[3], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[1], v[4], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[8], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[3], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[7], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[0], v[9], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[9], v[8], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[7], v[6], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[6], v[5], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[4], v[2], EdgeType.DIRECTED); + graph.addEdge(new Double(Math.random()), v[5], v[4], EdgeType.DIRECTED); + } + + public static void main(String[] args) + { + new VisualizationImageServerDemo(); + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/WorldMapGraphDemo.java libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/WorldMapGraphDemo.java --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/java/edu/uci/ics/jung/samples/WorldMapGraphDemo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/java/edu/uci/ics/jung/samples/WorldMapGraphDemo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.samples; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.ImageIcon; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.graph.DirectedSparseMultigraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.GraphZoomScrollPane; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; +import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner; + + +/** + * Shows a graph overlaid on a world map image. + * Scaling of the graph also scales the image background. + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class WorldMapGraphDemo extends JApplet { + + /** + * the graph + */ + Graph graph; + + /** + * the visual component and renderer for the graph + */ + VisualizationViewer vv; + + Map map = new HashMap(); + List cityList; + + + + /** + * create an instance of a simple graph with controls to + * demo the zoom features. + * + */ + public WorldMapGraphDemo() { + setLayout(new BorderLayout()); + + map.put("TYO", new String[] {"35 40 N", "139 45 E"}); + map.put("PEK", new String[] {"39 55 N", "116 26 E"}); + map.put("MOW", new String[] {"55 45 N", "37 42 E"}); + map.put("JRS", new String[] {"31 47 N", "35 13 E"}); + map.put("CAI", new String[] {"30 03 N", "31 15 E"}); + map.put("CPT", new String[] {"33 55 S", "18 22 E"}); + map.put("PAR", new String[] {"48 52 N", "2 20 E"}); + map.put("LHR", new String[] {"51 30 N", "0 10 W"}); + map.put("HNL", new String[] {"21 18 N", "157 51 W"}); + map.put("NYC", new String[] {"40 77 N", "73 98 W"}); + map.put("SFO", new String[] {"37 62 N", "122 38 W"}); + map.put("AKL", new String[] {"36 55 S", "174 47 E"}); + map.put("BNE", new String[] {"27 28 S", "153 02 E"}); + map.put("HKG", new String[] {"22 15 N", "114 10 E"}); + map.put("KTM", new String[] {"27 42 N", "85 19 E"}); + map.put("IST", new String[] {"41 01 N", "28 58 E"}); + map.put("STO", new String[] {"59 20 N", "18 03 E"}); + map.put("RIO", new String[] {"22 54 S", "43 14 W"}); + map.put("LIM", new String[] {"12 03 S", "77 03 W"}); + map.put("YTO", new String[] {"43 39 N", "79 23 W"}); + + cityList = new ArrayList(map.keySet()); + + // create a simple graph for the demo + graph = new DirectedSparseMultigraph(); + createVertices(); + createEdges(); + + ImageIcon mapIcon = null; + String imageLocation = "/images/political_world_map.jpg"; + try { + mapIcon = + new ImageIcon(getClass().getResource(imageLocation)); + } catch(Exception ex) { + System.err.println("Can't load \""+imageLocation+"\""); + } + final ImageIcon icon = mapIcon; + + Dimension layoutSize = new Dimension(2000,1000); + + Layout layout = new StaticLayout(graph, + Functions.compose( + new LatLonPixelTransformer(new Dimension(2000,1000)), + new CityTransformer(map)) + ); +// new ChainedTransformer(new Function[]{ +// new CityTransformer(map), +// new LatLonPixelTransformer(new Dimension(2000,1000)) +// })); + + layout.setSize(layoutSize); + vv = new VisualizationViewer(layout, + new Dimension(800,400)); + + if(icon != null) { + vv.addPreRenderPaintable(new VisualizationViewer.Paintable(){ + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + AffineTransform oldXform = g2d.getTransform(); + AffineTransform lat = + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getTransform(); + AffineTransform vat = + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getTransform(); + AffineTransform at = new AffineTransform(); + at.concatenate(g2d.getTransform()); + at.concatenate(vat); + at.concatenate(lat); + g2d.setTransform(at); + g.drawImage(icon.getImage(), 0, 0, + icon.getIconWidth(),icon.getIconHeight(),vv); + g2d.setTransform(oldXform); + } + public boolean useTransform() { return false; } + }); + } + + vv.getRenderer().setVertexRenderer( + new GradientVertexRenderer( + Color.white, Color.red, + Color.white, Color.blue, + vv.getPickedVertexState(), + false)); + + // add my listeners for ToolTips + vv.setVertexToolTipTransformer(new ToStringLabeller()); + vv.setEdgeToolTipTransformer(new Function() { + public String apply(Number edge) { + return "E"+graph.getEndpoints(edge).toString(); + }}); + + vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller()); + vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner()); + vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO); + + final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv); + add(panel); + final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse(); + vv.setGraphMouse(graphMouse); + + vv.addKeyListener(graphMouse.getModeKeyListener()); + vv.setToolTipText("

        Type 'p' for Pick mode

        Type 't' for Transform mode"); + + final ScalingControl scaler = new CrossoverScalingControl(); + + JButton plus = new JButton("+"); + plus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1.1f, vv.getCenter()); + } + }); + JButton minus = new JButton("-"); + minus.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + scaler.scale(vv, 1/1.1f, vv.getCenter()); + } + }); + + JButton reset = new JButton("reset"); + reset.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity(); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity(); + }}); + + JPanel controls = new JPanel(); + controls.add(plus); + controls.add(minus); + controls.add(reset); + add(controls, BorderLayout.SOUTH); + } + + /** + * create some vertices + * @param count how many to create + * @return the Vertices in an array + */ + private void createVertices() { + for (String city : map.keySet()) { + graph.addVertex(city); + } + } + + /** + * create edges for this demo graph + * @param v an array of Vertices to connect + */ + void createEdges() { + + for(int i=0; i { + + Map map; + public CityTransformer(Map map) { + this.map = map; + } + + /** + * transform airport code to latlon string + */ + public String[] apply(String city) { + return map.get(city); + } + } + + static class LatLonPixelTransformer implements Function { + Dimension d; + int startOffset; + + public LatLonPixelTransformer(Dimension d) { + this.d = d; + } + /** + * transform a lat + */ + public Point2D apply(String[] latlon) { + double latitude = 0; + double longitude = 0; + String[] lat = latlon[0].split(" "); + String[] lon = latlon[1].split(" "); + latitude = Integer.parseInt(lat[0]) + Integer.parseInt(lat[1])/60f; + latitude *= d.height/180f; + longitude = Integer.parseInt(lon[0]) + Integer.parseInt(lon[1])/60f; + longitude *= d.width/360f; + if(lat[2].equals("N")) { + latitude = d.height / 2 - latitude; + + } else { // assume S + latitude = d.height / 2 + latitude; + } + + if(lon[2].equals("W")) { + longitude = d.width / 2 - longitude; + + } else { // assume E + longitude = d.width / 2 + longitude; + } + + return new Point2D.Double(longitude,latitude); + } + + } + + public static void main(String[] args) { + // create a frome to hold the graph + final JFrame frame = new JFrame(); + Container content = frame.getContentPane(); + content.add(new WorldMapGraphDemo()); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/simple.net libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/simple.net --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/simple.net 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/simple.net 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,33 @@ +*Vertices 16 +1 "in1" +2 "in2" +3 "in3" +4 "in4" +5 "in5" +6 "in6" +7 "in7" +8 "in8" +9 "out1" +10 "out2" +11 "out3" +12 "out4" +13 "out5" +14 "out6" +15 "out7" +16 "out8" +*Edgeslist +1 2 5 8 9 16 +2 3 6 9 10 +3 4 7 10 11 +4 5 8 11 12 +5 6 12 13 +6 7 13 14 +7 8 14 15 +8 15 16 +9 10 16 +10 11 +11 12 +12 13 +13 14 +14 15 +15 16 diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/smyth.net libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/smyth.net --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/smyth.net 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/smyth.net 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,842 @@ +*Vertices 286 + 1 "M Pazzani" 0.0000 0.0000 0.5000 + 2 "M Fernandez" 0.0000 0.0000 0.5000 + 3 "O Mangasarian" 0.0000 0.0000 0.5000 + 4 "M Hearst" 0.0000 0.0000 0.5000 + 5 "M Jordan" 0.0000 0.0000 0.5000 + 6 "C Lai" 0.0000 0.0000 0.5000 + 7 "T Richardson" 0.0000 0.0000 0.5000 + 8 "C Meek" 0.0000 0.0000 0.5000 + 9 "C Glymour" 0.0000 0.0000 0.5000 + 10 "P Sabes" 0.0000 0.0000 0.5000 + 11 "J Frank" 0.0000 0.0000 0.5000 + 12 "P Cheeseman" 0.0000 0.0000 0.5000 + 13 "J Stutz" 0.0000 0.0000 0.5000 + 14 "M Wellman" 0.0000 0.0000 0.5000 + 15 "D Cohn" 0.0000 0.0000 0.5000 + 16 "A Smith" 0.0000 0.0000 0.5000 + 17 "B Draper" 0.0000 0.0000 0.5000 + 18 "J Erickson" 0.0000 0.0000 0.5000 + 19 "C Brodley" 0.0000 0.0000 0.5000 + 20 "P Smyth" 0.0000 0.0000 0.5000 + 21 "J Weber" 0.0000 0.0000 0.5000 + 22 "J Malik" 0.0000 0.0000 0.5000 + 23 "D Heckerman" 0.0000 0.0000 0.5000 + 24 "A Jones" 0.0000 0.0000 0.5000 + 25 "E Knill" 0.0000 0.0000 0.5000 + 26 "B Bollobas" 0.0000 0.0000 0.5000 + 27 "G Das" 0.0000 0.0000 0.5000 + 28 "D Gunopulos" 0.0000 0.0000 0.5000 + 29 "H Mannila" 0.0000 0.0000 0.5000 + 30 "S Teng" 0.0000 0.0000 0.5000 + 31 "D Mitchell" 0.0000 0.0000 0.5000 + 32 "R Khardon" 0.0000 0.0000 0.5000 + 33 "D Roth" 0.0000 0.0000 0.5000 + 34 "A Raftery" 0.0000 0.0000 0.5000 + 35 "D Madigan" 0.0000 0.0000 0.5000 + 36 "J Hoeting" 0.0000 0.0000 0.5000 + 37 "M Kersten" 0.0000 0.0000 0.5000 + 38 "O Miglino" 0.0000 0.0000 0.5000 + 39 "K Nafasi" 0.0000 0.0000 0.5000 + 40 "C Taylor" 0.0000 0.0000 0.5000 + 41 "D Wolpert" 0.0000 0.0000 0.5000 + 42 "W Macready" 0.0000 0.0000 0.5000 + 43 "A Hill" 0.0000 0.0000 0.5000 + 44 "T Cootes" 0.0000 0.0000 0.5000 + 45 "Z Ghahramani" 0.0000 0.0000 0.5000 + 46 "S Dumais" 0.0000 0.0000 0.5000 + 47 "P Chan" 0.0000 0.0000 0.5000 + 48 "S Soatto" 0.0000 0.0000 0.5000 + 49 "P Perona" 0.0000 0.0000 0.5000 + 50 "R Frezza" 0.0000 0.0000 0.5000 + 51 "G Picci" 0.0000 0.0000 0.5000 + 52 "M Mitchell" 0.0000 0.0000 0.5000 + 53 "T Jaakkola" 0.0000 0.0000 0.5000 + 54 "D Haussler" 0.0000 0.0000 0.5000 + 55 "P Orponen" 0.0000 0.0000 0.5000 + 56 "K Murphy" 0.0000 0.0000 0.5000 + 57 "H Greenspan" 0.0000 0.0000 0.5000 + 58 "S Belongie" 0.0000 0.0000 0.5000 + 59 "R Goodman" 0.0000 0.0000 0.5000 + 60 "M Holsheimer" 0.0000 0.0000 0.5000 + 61 "J Matousek" 0.0000 0.0000 0.5000 + 62 "L Xu" 0.0000 0.0000 0.5000 + 63 "M Paterson" 0.0000 0.0000 0.5000 + 64 "M Klemettinen" 0.0000 0.0000 0.5000 + 65 "H Toivonen" 0.0000 0.0000 0.5000 + 66 "A Weigend" 0.0000 0.0000 0.5000 + 67 "S Jung" 0.0000 0.0000 0.5000 + 68 "J Boulicaut" 0.0000 0.0000 0.5000 + 69 "S Casadei" 0.0000 0.0000 0.5000 + 70 "S Mitter" 0.0000 0.0000 0.5000 + 71 "J Adams" 0.0000 0.0000 0.5000 + 72 "J Kosecka" 0.0000 0.0000 0.5000 + 73 "R Paul" 0.0000 0.0000 0.5000 + 74 "A Farquhar" 0.0000 0.0000 0.5000 + 75 "R Kohavi" 0.0000 0.0000 0.5000 + 76 "M Jaeger" 0.0000 0.0000 0.5000 + 77 "J Ostrowski" 0.0000 0.0000 0.5000 + 78 "K Bennett" 0.0000 0.0000 0.5000 + 79 "A Ng" 0.0000 0.0000 0.5000 + 80 "P Ronkainen" 0.0000 0.0000 0.5000 + 81 "L Guibas" 0.0000 0.0000 0.5000 + 82 "B Dom" 0.0000 0.0000 0.5000 + 83 "M Sahami" 0.0000 0.0000 0.5000 + 84 "J Bouguet" 0.0000 0.0000 0.5000 + 85 "J Rice" 0.0000 0.0000 0.5000 + 86 "D Dobkin" 0.0000 0.0000 0.5000 + 87 "D Eppstein" 0.0000 0.0000 0.5000 + 88 "T Hastie" 0.0000 0.0000 0.5000 + 89 "P Agarwal" 0.0000 0.0000 0.5000 + 90 "E Ukkonen" 0.0000 0.0000 0.5000 + 91 "G Overton" 0.0000 0.0000 0.5000 + 92 "J Aaronson" 0.0000 0.0000 0.5000 + 93 "J Haas" 0.0000 0.0000 0.5000 + 94 "Z Wang" 0.0000 0.0000 0.5000 + 95 "D Hart" 0.0000 0.0000 0.5000 + 96 "G Gottlob" 0.0000 0.0000 0.5000 + 97 "P Stolorz" 0.0000 0.0000 0.5000 + 98 "F Yao" 0.0000 0.0000 0.5000 + 99 "A Robertson" 0.0000 0.0000 0.5000 + 100 "E Horvitz" 0.0000 0.0000 0.5000 + 101 "S Singh" 0.0000 0.0000 0.5000 + 102 "B Fischer" 0.0000 0.0000 0.5000 + 103 "T Leung" 0.0000 0.0000 0.5000 + 104 "H Ahonen" 0.0000 0.0000 0.5000 + 105 "O Heinonen" 0.0000 0.0000 0.5000 + 106 "P Kilpelainen" 0.0000 0.0000 0.5000 + 107 "M Atkinson" 0.0000 0.0000 0.5000 + 108 "D Peel" 0.0000 0.0000 0.5000 + 109 "G Miller" 0.0000 0.0000 0.5000 + 110 "S Russell" 0.0000 0.0000 0.5000 + 111 "W Buntine" 0.0000 0.0000 0.5000 + 112 "J Fortes" 0.0000 0.0000 0.5000 + 113 "L Saul" 0.0000 0.0000 0.5000 + 114 "M Dillencourt" 0.0000 0.0000 0.5000 + 115 "Y Weiss" 0.0000 0.0000 0.5000 + 116 "C Volinsky" 0.0000 0.0000 0.5000 + 117 "R Kronmal" 0.0000 0.0000 0.5000 + 118 "A Gray" 0.0000 0.0000 0.5000 + 119 "S Hanks" 0.0000 0.0000 0.5000 + 120 "V Tsaoussidis" 0.0000 0.0000 0.5000 + 121 "H Badr" 0.0000 0.0000 0.5000 + 122 "D Kriegman" 0.0000 0.0000 0.5000 + 123 "T Lane" 0.0000 0.0000 0.5000 + 124 "J Gilbert" 0.0000 0.0000 0.5000 + 125 "P Debevec" 0.0000 0.0000 0.5000 + 126 "J Kivinen" 0.0000 0.0000 0.5000 + 127 "J Crowcroft" 0.0000 0.0000 0.5000 + 128 "R Beigel" 0.0000 0.0000 0.5000 + 129 "A Mayer" 0.0000 0.0000 0.5000 + 130 "B MacLennan" 0.0000 0.0000 0.5000 + 131 "G Edwards" 0.0000 0.0000 0.5000 + 132 "C Matheus" 0.0000 0.0000 0.5000 + 133 "G Piatetsky-Shapiro" 0.0000 0.0000 0.5000 + 134 "D McNeill" 0.0000 0.0000 0.5000 + 135 "P Utgoff" 0.0000 0.0000 0.5000 + 136 "R Fikes" 0.0000 0.0000 0.5000 + 137 "R Jacobs" 0.0000 0.0000 0.5000 + 138 "M Weber" 0.0000 0.0000 0.5000 + 139 "J Gavrin" 0.0000 0.0000 0.5000 + 140 "K Chang" 0.0000 0.0000 0.5000 + 141 "D Hirschberg" 0.0000 0.0000 0.5000 + 142 "E Hunt" 0.0000 0.0000 0.5000 + 143 "S MacDonell" 0.0000 0.0000 0.5000 + 144 "Z Galil" 0.0000 0.0000 0.5000 + 145 "E Weydert" 0.0000 0.0000 0.5000 + 146 "D Thomas" 0.0000 0.0000 0.5000 + 147 "M Henzinger" 0.0000 0.0000 0.5000 + 148 "M Burl" 0.0000 0.0000 0.5000 + 149 "M Bern" 0.0000 0.0000 0.5000 + 150 "P Sozou" 0.0000 0.0000 0.5000 + 151 "J Graham" 0.0000 0.0000 0.5000 + 152 "E Demaine" 0.0000 0.0000 0.5000 + 153 "M Demaine" 0.0000 0.0000 0.5000 + 154 "S Spence" 0.0000 0.0000 0.5000 + 155 "D Geiger" 0.0000 0.0000 0.5000 + 156 "M Friedl" 0.0000 0.0000 0.5000 + 157 "T Eiter" 0.0000 0.0000 0.5000 + 158 "E Alpaydin" 0.0000 0.0000 0.5000 + 159 "S Solloway" 0.0000 0.0000 0.5000 + 160 "C Hutchinson" 0.0000 0.0000 0.5000 + 161 "J Waterton" 0.0000 0.0000 0.5000 + 162 "D Cooper" 0.0000 0.0000 0.5000 + 163 "A Barto" 0.0000 0.0000 0.5000 + 164 "E Nikunen" 0.0000 0.0000 0.5000 + 165 "E Dimauro" 0.0000 0.0000 0.5000 + 166 "G Linden" 0.0000 0.0000 0.5000 + 167 "A Verkamo" 0.0000 0.0000 0.5000 + 168 "I Verkamo" 0.0000 0.0000 0.5000 + 169 "L Goncalves" 0.0000 0.0000 0.5000 + 170 "G Cooper" 0.0000 0.0000 0.5000 + 171 "A Newton" 0.0000 0.0000 0.5000 + 172 "R Kraft" 0.0000 0.0000 0.5000 + 173 "J Breese" 0.0000 0.0000 0.5000 + 174 "N Amenta" 0.0000 0.0000 0.5000 + 175 "I Cadez" 0.0000 0.0000 0.5000 + 176 "C McLaren" 0.0000 0.0000 0.5000 + 177 "G McLachlan" 0.0000 0.0000 0.5000 + 178 "G Barequet" 0.0000 0.0000 0.5000 + 179 "M Meila" 0.0000 0.0000 0.5000 + 180 "Q Morris" 0.0000 0.0000 0.5000 + 181 "Y Song" 0.0000 0.0000 0.5000 + 182 "S Andersson" 0.0000 0.0000 0.5000 + 183 "M Perlman" 0.0000 0.0000 0.5000 + 184 "P Bradley" 0.0000 0.0000 0.5000 + 185 "U Fayyad" 0.0000 0.0000 0.5000 + 186 "D Wolf" 0.0000 0.0000 0.5000 + 187 "G Italiano" 0.0000 0.0000 0.5000 + 188 "K Tumer" 0.0000 0.0000 0.5000 + 189 "E Keogh" 0.0000 0.0000 0.5000 + 190 "E Bernardo" 0.0000 0.0000 0.5000 + 191 "E Ursella" 0.0000 0.0000 0.5000 + 192 "C Triggs" 0.0000 0.0000 0.5000 + 193 "D Sornette" 0.0000 0.0000 0.5000 + 194 "E Friedman" 0.0000 0.0000 0.5000 + 195 "L Daynes" 0.0000 0.0000 0.5000 + 196 "T Printezis" 0.0000 0.0000 0.5000 + 197 "T Pressburger" 0.0000 0.0000 0.5000 + 198 "B Tuttle" 0.0000 0.0000 0.5000 + 199 "J Haslam" 0.0000 0.0000 0.5000 + 200 "G Page" 0.0000 0.0000 0.5000 + 201 "C Jackson" 0.0000 0.0000 0.5000 + 202 "C Bishop" 0.0000 0.0000 0.5000 + 203 "D Pavlov" 0.0000 0.0000 0.5000 + 204 "M Dickerson" 0.0000 0.0000 0.5000 + 205 "N de Freitas" 0.0000 0.0000 0.5000 + 206 "C Stauss" 0.0000 0.0000 0.5000 + 207 "R Kilgour" 0.0000 0.0000 0.5000 + 208 "R Manduchi" 0.0000 0.0000 0.5000 + 209 "G Graefe" 0.0000 0.0000 0.5000 + 210 "R Shachter" 0.0000 0.0000 0.5000 + 211 "K Mosurski" 0.0000 0.0000 0.5000 + 212 "R Almond" 0.0000 0.0000 0.5000 + 213 "D Young" 0.0000 0.0000 0.5000 + 214 "A Lapedes" 0.0000 0.0000 0.5000 + 215 "R Blasi" 0.0000 0.0000 0.5000 + 216 "D Chickering" 0.0000 0.0000 0.5000 + 217 "R Giancarlo" 0.0000 0.0000 0.5000 + 218 "K Wheeler" 0.0000 0.0000 0.5000 + 219 "A Lanitis" 0.0000 0.0000 0.5000 + 220 "P Prado" 0.0000 0.0000 0.5000 + 221 "X Ge" 0.0000 0.0000 0.5000 + 222 "S Payandeh" 0.0000 0.0000 0.5000 + 223 "M Ghil" 0.0000 0.0000 0.5000 + 224 "K Ide" 0.0000 0.0000 0.5000 + 225 "H King" 0.0000 0.0000 0.5000 + 226 "I Dryden" 0.0000 0.0000 0.5000 + 227 "B Thiesson" 0.0000 0.0000 0.5000 + 228 "D Pregibon" 0.0000 0.0000 0.5000 + 229 "A Korhola" 0.0000 0.0000 0.5000 + 230 "H Olander" 0.0000 0.0000 0.5000 + 231 "W Pratt" 0.0000 0.0000 0.5000 + 232 "R Engelmore" 0.0000 0.0000 0.5000 + 233 "A Brett" 0.0000 0.0000 0.5000 + 234 "C Sayers" 0.0000 0.0000 0.5000 + 235 "J Mao" 0.0000 0.0000 0.5000 + 236 "M Salmenkivi" 0.0000 0.0000 0.5000 + 237 "A Mamdani" 0.0000 0.0000 0.5000 + 238 "J Iv" 0.0000 0.0000 0.5000 + 239 "M Welling" 0.0000 0.0000 0.5000 + 240 "B Kanefsky" 0.0000 0.0000 0.5000 + 241 "W Taylor" 0.0000 0.0000 0.5000 + 242 "C Strauss" 0.0000 0.0000 0.5000 + 243 "K Walker" 0.0000 0.0000 0.5000 + 244 "M Faghihi" 0.0000 0.0000 0.5000 + 245 "E Di Bernardo" 0.0000 0.0000 0.5000 + 246 "P Kube" 0.0000 0.0000 0.5000 + 247 "K Rommelse" 0.0000 0.0000 0.5000 + 248 "D Rumelhart" 0.0000 0.0000 0.5000 + 249 "S Gaffney" 0.0000 0.0000 0.5000 + 250 "C Reina" 0.0000 0.0000 0.5000 + 251 "S Chaudhuiri" 0.0000 0.0000 0.5000 + 252 "P Sallis" 0.0000 0.0000 0.5000 + 253 "K Laakso" 0.0000 0.0000 0.5000 + 254 "B Levidow" 0.0000 0.0000 0.5000 + 255 "D Donnell" 0.0000 0.0000 0.5000 + 256 "M Tartagni" 0.0000 0.0000 0.5000 + 257 "M Vanter" 0.0000 0.0000 0.5000 + 258 "N Lawrence" 0.0000 0.0000 0.5000 + 259 "C Fowlkes" 0.0000 0.0000 0.5000 + 260 "J Roden" 0.0000 0.0000 0.5000 + 261 "G Ridgeway" 0.0000 0.0000 0.5000 + 262 "E Kuo" 0.0000 0.0000 0.5000 + 263 "L Su" 0.0000 0.0000 0.5000 + 264 "M Munich" 0.0000 0.0000 0.5000 + 265 "D Golinelli" 0.0000 0.0000 0.5000 + 266 "G Consonni" 0.0000 0.0000 0.5000 + 267 "D Cunliffe" 0.0000 0.0000 0.5000 + 268 "D Psaltis" 0.0000 0.0000 0.5000 + 269 "G Steckman" 0.0000 0.0000 0.5000 + 270 "P Courtier" 0.0000 0.0000 0.5000 + 271 "M Latif" 0.0000 0.0000 0.5000 + 272 "I Sim" 0.0000 0.0000 0.5000 + 273 "L Cordero" 0.0000 0.0000 0.5000 + 274 "L Ugarte" 0.0000 0.0000 0.5000 + 275 "K Pentikousis" 0.0000 0.0000 0.5000 + 276 "N Kapadia" 0.0000 0.0000 0.5000 + 277 "J seck" 0.0000 0.0000 0.5000 + 278 "F Lott" 0.0000 0.0000 0.5000 + 279 "D Chudova" 0.0000 0.0000 0.5000 + 280 "P Yiou" 0.0000 0.0000 0.5000 + 281 "W Einhauser" 0.0000 0.0000 0.5000 + 282 "P Vetter" 0.0000 0.0000 0.5000 + 283 "S Goodbody" 0.0000 0.0000 0.5000 + 284 "M Kawato" 0.0000 0.0000 0.5000 + 285 "P Hrensen" 0.0000 0.0000 0.5000 + 286 "M Levitz" 0.0000 0.0000 0.5000 +*Edges + 23 237 1 + 203 279 2 + 171 263 1 + 116 117 1 + 41 214 1 + 87 124 1 + 54 126 2 + 265 266 1 + 40 67 2 + 5 53 17 + 166 167 3 + 87 217 2 + 63 87 1 + 49 169 3 + 75 83 2 + 49 70 1 + 49 69 1 + 71 222 1 + 223 280 1 + 49 246 1 + 231 232 1 + 40 215 2 + 5 158 1 + 29 60 1 + 20 228 1 + 17 19 1 + 16 127 1 + 152 194 1 + 58 59 1 + 108 220 1 + 30 109 4 + 74 232 1 + 40 200 1 + 29 166 1 + 29 167 3 + 40 125 3 + 20 40 1 + 49 138 8 + 89 174 2 + 11 13 1 + 11 12 1 + 169 181 1 + 28 29 4 + 29 105 1 + 44 219 4 + 29 55 1 + 65 167 3 + 133 185 1 + 20 49 1 + 8 216 2 + 5 202 3 + 148 185 1 + 41 284 1 + 44 162 1 + 83 100 1 + 22 58 7 + 22 57 4 + 16 71 1 + 20 41 1 + 193 223 1 + 151 162 1 + 102 111 1 + 121 275 1 + 184 250 3 + 29 65 13 + 29 64 4 + 82 203 1 + 40 199 2 + 118 207 1 + 87 149 14 + 136 231 3 + 40 165 2 + 30 174 2 + 54 185 1 + 20 221 5 + 41 188 5 + 5 20 2 + 41 130 3 + 6 224 1 + 182 192 2 + 268 269 1 + 203 221 1 + 86 87 1 + 172 240 1 + 5 115 1 + 144 187 4 + 228 238 1 + 155 185 1 + 36 116 1 + 35 255 1 + 159 160 2 + 159 161 2 + 105 167 4 + 49 148 9 + 175 249 1 + 96 157 7 + 49 269 1 + 104 164 1 + 1 114 1 + 35 228 1 + 87 141 3 + 54 97 1 + 142 254 1 + 142 255 1 + 87 114 1 + 35 254 1 + 5 163 1 + 5 154 1 + 175 177 3 + 175 176 3 + 149 262 1 + 150 165 2 + 183 192 2 + 26 28 2 + 26 27 2 + 26 29 2 + 74 136 7 + 152 262 1 + 94 127 9 + 71 127 1 + 88 228 1 + 149 174 6 + 56 205 1 + 1 189 5 + 101 113 2 + 49 239 4 + 84 138 1 + 182 183 7 + 99 278 1 + 57 58 6 + 200 201 1 + 30 87 3 + 236 253 1 + 29 126 3 + 129 263 1 + 119 166 2 + 87 194 1 + 71 146 1 + 27 28 3 + 27 29 5 + 71 93 1 + 71 91 1 + 47 132 1 + 47 133 1 + 18 89 4 + 24 40 1 + 29 203 2 + 29 76 1 + 187 217 1 + 137 163 1 + 193 280 1 + 5 23 2 + 205 285 1 + 71 92 1 + 40 150 3 + 282 283 1 + 118 143 3 + 19 156 1 + 16 94 1 + 223 224 3 + 48 72 2 + 1 141 1 + 5 179 6 + 5 180 2 + 7 8 3 + 29 80 3 + 41 45 10 + 13 172 1 + 154 195 1 + 40 277 1 + 40 72 1 + 29 37 1 + 23 179 1 + 20 203 5 + 124 149 1 + 129 171 1 + 12 20 1 + 46 100 1 + 63 98 1 + 40 244 1 + 185 251 1 + 18 87 4 + 69 70 8 + 223 278 1 + 20 231 1 + 259 260 1 + 35 36 4 + 9 228 1 + 133 134 1 + 273 274 1 + 14 23 1 + 20 249 2 + 20 29 3 + 44 151 1 + 29 229 1 + 29 164 2 + 111 197 1 + 35 117 1 + 21 40 1 + 8 23 6 + 56 115 2 + 19 135 4 + 49 181 1 + 64 68 2 + 40 162 1 + 13 240 1 + 15 101 2 + 35 211 1 + 35 212 2 + 56 110 5 + 25 41 1 + 28 86 3 + 87 221 1 + 87 109 1 + 2 118 1 + 5 10 4 + 155 225 1 + 87 95 1 + 25 54 1 + 203 235 1 + 37 60 2 + 49 50 3 + 6 140 1 + 41 283 1 + 46 83 1 + 40 233 3 + 49 57 2 + 32 33 12 + 71 73 1 + 87 262 1 + 71 234 1 + 35 261 2 + 29 104 2 + 15 45 4 + 12 13 3 + 29 106 1 + 87 178 2 + 44 165 2 + 43 233 2 + 3 185 1 + 65 253 1 + 65 236 1 + 87 98 1 + 35 265 1 + 87 89 2 + 221 249 1 + 149 152 1 + 120 221 1 + 9 20 1 + 49 58 2 + 44 199 2 + 179 180 2 + 34 116 3 + 23 225 1 + 40 160 2 + 40 159 2 + 44 201 1 + 111 129 1 + 49 51 1 + 8 225 1 + 129 144 1 + 79 110 3 + 5 107 3 + 18 81 3 + 20 185 3 + 81 147 1 + 106 166 2 + 20 279 2 + 35 183 8 + 35 182 7 + 111 171 1 + 49 281 1 + 185 250 3 + 40 44 20 + 40 43 5 + 27 80 2 + 29 96 1 + 264 269 1 + 264 268 1 + 203 249 1 + 221 275 1 + 183 286 1 + 23 46 1 + 73 234 4 + 49 268 1 + 5 62 2 + 76 145 1 + 49 185 1 + 5 248 1 + 138 281 1 + 178 204 6 + 58 103 3 + 105 106 1 + 19 20 1 + 209 251 1 + 20 71 1 + 22 277 1 + 160 161 2 + 22 103 7 + 57 59 2 + 28 32 1 + 169 191 1 + 169 190 1 + 48 50 4 + 61 87 1 + 60 65 1 + 41 218 3 + 5 195 1 + 5 196 1 + 74 231 3 + 22 72 1 + 29 68 2 + 138 148 3 + 3 78 4 + 12 172 1 + 22 215 2 + 10 41 2 + 5 101 5 + 19 112 2 + 110 285 1 + 164 166 1 + 7 35 2 + 121 221 1 + 5 258 2 + 22 110 2 + 226 244 1 + 20 224 2 + 103 148 4 + 140 223 1 + 14 237 1 + 29 168 1 + 49 59 1 + 53 113 4 + 23 247 2 + 81 89 4 + 23 155 11 + 240 241 1 + 64 104 8 + 101 163 3 + 20 189 1 + 5 56 1 + 43 44 2 + 65 168 1 + 6 223 1 + 29 90 2 + 45 53 2 + 111 263 1 + 50 51 2 + 5 137 3 + 100 170 1 + 35 139 2 + 211 212 1 + 23 100 2 + 44 200 1 + 44 131 6 + 21 22 6 + 49 208 1 + 53 54 3 + 254 255 1 + 148 260 1 + 148 259 1 + 153 194 1 + 87 147 1 + 35 192 2 + 23 216 5 + 181 245 1 + 49 191 1 + 49 190 1 + 19 276 2 + 4 83 2 + 92 93 3 + 49 103 4 + 89 147 1 + 71 198 1 + 136 232 1 + 5 45 21 + 64 167 4 + 19 123 7 + 40 151 1 + 20 118 1 + 35 286 1 + 112 276 2 + 40 77 2 + 239 281 1 + 81 87 1 + 81 86 1 + 23 170 2 + 5 110 1 + 185 209 1 + 91 93 3 + 91 92 3 + 82 235 1 + 29 236 1 + 155 216 1 + 40 243 3 + 40 122 2 + 53 179 4 + 107 154 1 + 173 247 2 + 110 205 2 + 104 106 1 + 184 185 5 + 41 206 1 + 87 144 4 + 34 117 1 + 107 196 1 + 30 124 4 + 23 173 4 + 118 252 1 + 5 205 1 + 67 77 2 + 41 186 3 + 120 275 1 + 215 277 1 + 143 252 1 + 20 148 1 + 18 152 1 + 20 223 2 + 64 105 10 + 99 271 1 + 23 227 1 + 29 157 2 + 2 273 1 + 2 274 1 + 20 175 5 + 20 176 3 + 20 177 3 + 61 89 6 + 49 256 1 + 177 220 1 + 41 75 1 + 20 133 1 + 87 152 2 + 5 79 1 + 78 155 1 + 20 23 3 + 35 116 4 + 22 40 6 + 35 266 1 + 43 199 1 + 116 182 1 + 116 183 1 + 85 136 4 + 140 224 1 + 66 111 1 + 107 195 3 + 29 253 1 + 34 36 4 + 34 35 7 + 5 15 3 + 5 257 1 + 87 153 1 + 74 85 5 + 118 213 1 + 106 164 1 + 4 231 1 + 229 230 1 + 41 282 1 + 138 239 4 + 29 32 3 + 29 33 2 + 44 150 3 + 40 71 1 + 104 167 3 + 40 201 1 + 53 101 7 + 221 231 1 + 131 219 1 + 23 83 1 + 45 113 4 + 231 272 1 + 64 65 2 + 190 191 1 + 90 126 2 + 71 94 1 + 29 145 1 + 3 184 8 + 29 230 1 + 34 139 1 + 5 285 1 + 40 219 4 + 22 125 6 + 72 215 1 + 23 210 1 + 20 35 1 + 31 87 1 + 31 86 1 + 53 258 1 + 152 153 5 + 85 231 1 + 41 42 8 + 65 229 1 + 65 230 1 + 35 142 1 + 120 121 6 + 169 245 2 + 61 81 1 + 40 52 1 + 30 149 2 + 87 204 3 + 49 264 5 + 40 161 2 + 7 261 2 + 12 111 1 + 20 87 1 + 44 243 3 + 99 223 2 + 97 185 1 + 35 119 1 + 8 227 1 + 12 240 2 + 12 241 1 + 39 40 1 + 8 155 2 + 216 227 1 + 102 197 1 + 17 135 1 + 78 185 1 + 104 105 10 + 202 258 4 + 103 138 1 + 5 113 12 + 108 177 7 + 48 49 11 + 48 51 2 + 224 270 1 + 87 174 4 + 5 41 10 + 20 111 2 + 40 226 1 + 119 139 1 + 223 271 1 + 87 187 3 + 9 35 1 + 49 245 2 + 118 274 1 + 118 273 1 + 8 170 1 + 176 177 3 + 49 84 9 + 37 65 1 + 114 141 1 + 40 267 1 + 118 185 1 + 41 242 1 + 132 133 3 + 132 134 1 + 53 202 1 + 144 217 2 + 40 131 6 + 188 218 2 + 87 128 2 + 38 39 1 + 38 40 1 diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/weighted.net libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/weighted.net --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/weighted.net 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/weighted.net 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,8 @@ +*Vertices 3 +1 "in1" +2 "in2" +3 "in3" +*Edges +1 2 10 10 +1 3 1 1 +2 3 5 5 diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/zachary.net libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/zachary.net --- libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/datasets/zachary.net 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/main/resources/datasets/zachary.net 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,114 @@ +*Vertices 34 + 1 "1" 0.6680 0.3596 0.5000 + 2 "2" 0.7146 0.5745 0.5000 + 3 "3" 0.5470 0.4607 0.5000 + 4 "4" 0.7270 0.4813 0.5000 + 5 "5" 0.7150 0.1929 0.5000 + 6 "6" 0.7813 0.1330 0.5000 + 7 "7" 0.8013 0.1929 0.5000 + 8 "8" 0.7424 0.5463 0.5000 + 9 "9" 0.5510 0.5262 0.5000 + 10 "10" 0.4630 0.5356 0.5000 + 11 "11" 0.6873 0.1338 0.5000 + 12 "12" 0.8413 0.3596 0.5000 + 13 "13" 0.8036 0.4532 0.5000 + 14 "14" 0.6116 0.5443 0.5000 + 15 "15" 0.2306 0.8916 0.5000 + 16 "16" 0.3470 0.9505 0.5000 + 17 "17" 0.8663 0.1330 0.5000 + 18 "18" 0.8100 0.5468 0.5000 + 19 "19" 0.2077 0.8501 0.5000 + 20 "20" 0.6283 0.5955 0.5000 + 21 "21" 0.3115 0.9469 0.5000 + 22 "22" 0.7942 0.5784 0.5000 + 23 "23" 0.2660 0.9264 0.5000 + 24 "24" 0.2383 0.5472 0.5000 + 25 "25" 0.2823 0.2970 0.5000 + 26 "26" 0.2306 0.3616 0.5000 + 27 "27" 0.1850 0.7828 0.5000 + 28 "28" 0.3373 0.4704 0.5000 + 29 "29" 0.3827 0.5160 0.5000 + 30 "30" 0.2060 0.6628 0.5000 + 31 "31" 0.5619 0.7032 0.5000 + 32 "32" 0.4127 0.4366 0.5000 + 33 "33" 0.4016 0.6960 0.5000 + 34 "34" 0.3830 0.6161 0.5000 +*Edges + 1 2 2 + 1 3 2 + 1 4 2 + 1 5 2 + 1 6 2 + 1 7 2 + 1 8 2 + 1 9 2 + 1 11 2 + 1 12 2 + 1 13 2 + 1 14 2 + 1 18 2 + 1 20 2 + 1 22 2 + 1 32 2 + 2 3 2 + 2 4 2 + 2 8 2 + 2 14 2 + 2 18 2 + 2 20 2 + 2 22 2 + 2 31 2 + 3 4 2 + 3 8 2 + 3 9 2 + 3 10 2 + 3 14 2 + 3 28 2 + 3 29 2 + 3 33 2 + 4 8 2 + 4 13 2 + 4 14 2 + 5 7 2 + 5 11 2 + 6 7 2 + 6 11 2 + 6 17 2 + 7 17 2 + 9 31 2 + 9 33 2 + 9 34 2 + 10 34 2 + 14 34 2 + 15 33 2 + 15 34 2 + 16 33 2 + 16 34 2 + 19 33 2 + 19 34 2 + 20 34 2 + 21 33 2 + 21 34 2 + 23 33 2 + 23 34 2 + 24 26 2 + 24 28 2 + 24 30 2 + 24 33 2 + 24 34 2 + 25 26 2 + 25 28 2 + 25 32 2 + 26 32 2 + 27 30 2 + 27 34 2 + 28 34 2 + 29 32 2 + 29 34 2 + 30 33 2 + 30 34 2 + 31 33 2 + 31 34 2 + 32 33 2 + 32 34 2 + 33 34 2 Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/china.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/china.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/france.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/france.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/germany.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/germany.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/japan.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/japan.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/lightning-s.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/lightning-s.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/political_world_map.jpg and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/political_world_map.jpg differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/russia.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/russia.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/Sandstone.jpg and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/Sandstone.jpg differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/spain.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/spain.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicapple.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicapple.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicgamespcgames.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicgamespcgames.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicgraphics3.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicgraphics3.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topichumor.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topichumor.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicinputdevices.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicinputdevices.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topiclinux.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topiclinux.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicmusic.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicmusic.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicos.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicos.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicprivacy.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicprivacy.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicsample2.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicsample2.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicsample.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicsample.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicwireless.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicwireless.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/topicx.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/topicx.gif differ Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples/src/main/resources/images/united-states.gif and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples/src/main/resources/images/united-states.gif differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-samples/src/site/site.xml libjung-free-java-2.1.1/jung-samples/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-samples/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-samples/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + +

        + + + + + Binary files /tmp/tmp1zpazht3/4bHdh8l1kh/libjung-free-java-2.0.1+dfsg/jung-samples-2.0.1-sources.jar and /tmp/tmp1zpazht3/UuBXexv9TA/libjung-free-java-2.1.1/jung-samples-2.0.1-sources.jar differ diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/assembly.xml libjung-free-java-2.1.1/jung-visualization/assembly.xml --- libjung-free-java-2.0.1+dfsg/jung-visualization/assembly.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/assembly.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + dependencies + + tar.gz + + false + + + / + false + runtime + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/pom.xml libjung-free-java-2.1.1/jung-visualization/pom.xml --- libjung-free-java-2.0.1+dfsg/jung-visualization/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ + + + 4.0.0 + + net.sf.jung + jung-parent + 2.1.1 + + jung-visualization + JUNG - Visualization Support + Core visualization support for the JUNG project + + + + net.sf.jung + jung-api + ${project.version} + + + net.sf.jung + jung-algorithms + ${project.version} + + + net.sf.jung + jung-graph-impl + ${project.version} + test + + + junit + junit + test + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +import javax.swing.JComponent; +import javax.swing.JOptionPane; + +import edu.uci.ics.jung.visualization.MultiLayerTransformer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.control.AbstractGraphMousePlugin; + +/** + * AnnotatingGraphMousePlugin can create Shape and Text annotations + * in a layer of the graph visualization. + * + * @author Tom Nelson + */ +public class AnnotatingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + * additional modifiers for the action of adding to an existing + * selection + */ + protected int additionalModifiers; + + /** + * used to draw a Shape annotation + */ + protected RectangularShape rectangularShape = new Rectangle2D.Float(); + + /** + * the Paintable for the Shape annotation + */ + protected Paintable lensPaintable; + + /** + * a Paintable to store all Annotations + */ + protected AnnotationManager annotationManager; + + /** + * color for annotations + */ + protected Color annotationColor = Color.cyan; + + /** + * layer for annotations + */ + protected Annotation.Layer layer = Annotation.Layer.LOWER; + + protected boolean fill; + + /** + * holds rendering transforms + */ + protected MultiLayerTransformer basicTransformer; + + /** + * holds rendering settings + */ + protected RenderContext rc; + + /** + * set to true when the AnnotationPaintable has been + * added to the view component + */ + protected boolean added = false; + + /** + * Create an instance with defaults for primary (button 1) and secondary + * (button 1 + shift) selection. + * @param rc the RenderContext for which this plugin will be used + */ + public AnnotatingGraphMousePlugin(RenderContext rc) { + this(rc, InputEvent.BUTTON1_MASK, + InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK); + } + + /** + * Create an instance with the specified primary and secondary selection + * mechanisms. + * @param rc the RenderContext for which this plugin will be used + * @param selectionModifiers for primary selection + * @param additionalModifiers for additional selection + */ + public AnnotatingGraphMousePlugin(RenderContext rc, + int selectionModifiers, int additionalModifiers) { + super(selectionModifiers); + this.rc = rc; + this.basicTransformer = rc.getMultiLayerTransformer(); + this.additionalModifiers = additionalModifiers; + this.lensPaintable = new LensPaintable(); + this.annotationManager = new AnnotationManager(rc); + this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + } + + /** + * @return Returns the lensColor. + */ + public Color getAnnotationColor() { + return annotationColor; + } + + /** + * @param lensColor The lensColor to set. + */ + public void setAnnotationColor(Color lensColor) { + this.annotationColor = lensColor; + } + + /** + * the Paintable that draws a Shape annotation + * only while it is being created + * + */ + class LensPaintable implements Paintable { + + public void paint(Graphics g) { + Color oldColor = g.getColor(); + g.setColor(annotationColor); + ((Graphics2D)g).draw(rectangularShape); + g.setColor(oldColor); + } + + public boolean useTransform() { + return false; + } + } + + /** + * Sets the location for an Annotation. + * Will either pop up a dialog to prompt for text + * input for a text annotation, or begin the process + * of drawing a Shape annotation + * + * @param e the event + */ + @SuppressWarnings("unchecked") + public void mousePressed(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + down = e.getPoint(); + + if(added == false) { + vv.addPreRenderPaintable(annotationManager.getLowerAnnotationPaintable()); + vv.addPostRenderPaintable(annotationManager.getUpperAnnotationPaintable()); + added = true; + } + + + if(e.isPopupTrigger()) { + String annotationString = JOptionPane.showInputDialog(vv,"Annotation:"); + if(annotationString != null && annotationString.length() > 0) { + Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down); + Annotation annotation = + new Annotation(annotationString, layer, annotationColor, fill, p); + annotationManager.add(layer, annotation); + } + } else if(e.getModifiers() == additionalModifiers) { + Annotation annotation = annotationManager.getAnnotation(down); + annotationManager.remove(annotation); + } else if(e.getModifiers() == modifiers) { + rectangularShape.setFrameFromDiagonal(down,down); + vv.addPostRenderPaintable(lensPaintable); + } + vv.repaint(); + } + + /** + * Completes the process of adding a Shape annotation + * and removed the transient paintable + * + */ + @SuppressWarnings("unchecked") + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + if(e.isPopupTrigger()) { + String annotationString = JOptionPane.showInputDialog(vv,"Annotation:"); + if(annotationString != null && annotationString.length() > 0) { + Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down); + Annotation annotation = + new Annotation(annotationString, layer, annotationColor, fill, p); + annotationManager.add(layer, annotation); + } + } else if(e.getModifiers() == modifiers) { + if(down != null) { + Point2D out = e.getPoint(); + RectangularShape arect = (RectangularShape)rectangularShape.clone(); + arect.setFrameFromDiagonal(down,out); + Shape s = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(arect); + Annotation annotation = + new Annotation(s, layer, annotationColor, fill, out); + annotationManager.add(layer, annotation); + } + } + down = null; + vv.removePostRenderPaintable(lensPaintable); + vv.repaint(); + } + + /** + * Draws the transient Paintable that will become + * a Shape annotation when the mouse button is + * released + * + */ + @SuppressWarnings("unchecked") + public void mouseDragged(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + + Point2D out = e.getPoint(); + if(e.getModifiers() == additionalModifiers) { + rectangularShape.setFrameFromDiagonal(down,out); + + } else if(e.getModifiers() == modifiers) { + rectangularShape.setFrameFromDiagonal(down,out); + + } + rectangularShape.setFrameFromDiagonal(down,out); + vv.repaint(); + } + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(cursor); + } + + public void mouseExited(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + public void mouseMoved(MouseEvent e) { + } + + /** + * @return the rect + */ + public RectangularShape getRectangularShape() { + return rectangularShape; + } + + /** + * @param rect the rect to set + */ + public void setRectangularShape(RectangularShape rect) { + this.rectangularShape = rect; + } + + /** + * @return the layer + */ + public Annotation.Layer getLayer() { + return layer; + } + + /** + * @param layer the layer to set + */ + public void setLayer(Annotation.Layer layer) { + this.layer = layer; + } + + /** + * @return the fill + */ + public boolean isFill() { + return fill; + } + + /** + * @param fill the fill to set + */ + public void setFill(boolean fill) { + this.fill = fill; + } + + } diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingModalGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingModalGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingModalGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotatingModalGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.ItemSelectable; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.plaf.basic.BasicIconFactory; + +import edu.uci.ics.jung.visualization.MultiLayerTransformer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse; +import edu.uci.ics.jung.visualization.control.AnimatedPickingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.CrossoverScalingControl; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.PickingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.RotatingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ScalingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.ShearingGraphMousePlugin; +import edu.uci.ics.jung.visualization.control.TranslatingGraphMousePlugin; + +/** + * a graph mouse that supplies an annotations mode + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class AnnotatingModalGraphMouse extends AbstractModalGraphMouse + implements ModalGraphMouse, ItemSelectable { + + protected AnnotatingGraphMousePlugin annotatingPlugin; + protected MultiLayerTransformer basicTransformer; + protected RenderContext rc; + + /** + * Create an instance with default values for scale in (1.1) and scale out (1/1.1). + * + * @param rc the RenderContext for which this class will be used + * @param annotatingPlugin the plugin used by this class for annotating + */ + public AnnotatingModalGraphMouse(RenderContext rc, + AnnotatingGraphMousePlugin annotatingPlugin) { + this(rc, annotatingPlugin, 1.1f, 1/1.1f); + } + + /** + * Create an instance with the specified scale in and scale out values. + * + * @param rc the RenderContext for which this class will be used + * @param annotatingPlugin the plugin used by this class for annotating + * @param in override value for scale in + * @param out override value for scale out + */ + public AnnotatingModalGraphMouse(RenderContext rc, + AnnotatingGraphMousePlugin annotatingPlugin, + float in, float out) { + super(in,out); + this.rc = rc; + this.basicTransformer = rc.getMultiLayerTransformer(); + this.annotatingPlugin = annotatingPlugin; + loadPlugins(); + setModeKeyListener(new ModeKeyAdapter(this)); + } + + /** + * create the plugins, and load the plugins for TRANSFORMING mode + * + */ + @Override + protected void loadPlugins() { + this.pickingPlugin = new PickingGraphMousePlugin(); + this.animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + this.translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + this.scalingPlugin = new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out); + this.rotatingPlugin = new RotatingGraphMousePlugin(); + this.shearingPlugin = new ShearingGraphMousePlugin(); + add(scalingPlugin); + setMode(Mode.TRANSFORMING); + } + + /** + * setter for the Mode. + */ + @Override + public void setMode(Mode mode) { + if(this.mode != mode) { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + this.mode, ItemEvent.DESELECTED)); + this.mode = mode; + if(mode == Mode.TRANSFORMING) { + setTransformingMode(); + } else if(mode == Mode.PICKING) { + setPickingMode(); + } else if(mode == Mode.ANNOTATING) { + setAnnotatingMode(); + } + if(modeBox != null) { + modeBox.setSelectedItem(mode); + } + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, mode, ItemEvent.SELECTED)); + } + } + + @Override + protected void setPickingMode() { + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + remove(annotatingPlugin); + add(pickingPlugin); + add(animatedPickingPlugin); + } + + @Override + protected void setTransformingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(annotatingPlugin); + add(translatingPlugin); + add(rotatingPlugin); + add(shearingPlugin); + } + + protected void setEditingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + remove(annotatingPlugin); + } + + protected void setAnnotatingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + add(annotatingPlugin); + } + + + /** + * @return Returns the modeBox. + */ + @Override + public JComboBox getModeComboBox() { + if(modeBox == null) { + modeBox = new JComboBox( + new Mode[]{Mode.TRANSFORMING, Mode.PICKING, Mode.ANNOTATING}); + modeBox.addItemListener(getModeListener()); + } + modeBox.setSelectedItem(mode); + return modeBox; + } + + /** + * create (if necessary) and return a menu that will change + * the mode + * @return the menu + */ + @Override + public JMenu getModeMenu() { + if(modeMenu == null) { + modeMenu = new JMenu();// { + Icon icon = BasicIconFactory.getMenuArrowIcon(); + modeMenu.setIcon(BasicIconFactory.getMenuArrowIcon()); + modeMenu.setPreferredSize(new Dimension(icon.getIconWidth()+10, + icon.getIconHeight()+10)); + + final JRadioButtonMenuItem transformingButton = + new JRadioButtonMenuItem(Mode.TRANSFORMING.toString()); + transformingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.TRANSFORMING); + } + }}); + + final JRadioButtonMenuItem pickingButton = + new JRadioButtonMenuItem(Mode.PICKING.toString()); + pickingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.PICKING); + } + }}); + + ButtonGroup radio = new ButtonGroup(); + radio.add(transformingButton); + radio.add(pickingButton); + transformingButton.setSelected(true); + modeMenu.add(transformingButton); + modeMenu.add(pickingButton); + modeMenu.setToolTipText("Menu for setting Mouse Mode"); + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + if(e.getItem() == Mode.TRANSFORMING) { + transformingButton.setSelected(true); + } else if(e.getItem() == Mode.PICKING) { + pickingButton.setSelected(true); + } + } + }}); + } + return modeMenu; + } + + public static class ModeKeyAdapter extends KeyAdapter { + private char t = 't'; + private char p = 'p'; + private char a = 'a'; + protected ModalGraphMouse graphMouse; + + public ModeKeyAdapter(ModalGraphMouse graphMouse) { + this.graphMouse = graphMouse; + } + + public ModeKeyAdapter(char t, char p, char a, ModalGraphMouse graphMouse) { + this.t = t; + this.p = p; + this.a = a; + this.graphMouse = graphMouse; + } + + @Override + public void keyTyped(KeyEvent event) { + char keyChar = event.getKeyChar(); + if(keyChar == t) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + graphMouse.setMode(Mode.TRANSFORMING); + } else if(keyChar == p) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + graphMouse.setMode(Mode.PICKING); + } else if(keyChar == a) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + graphMouse.setMode(Mode.ANNOTATING); + } + } + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationControls.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationControls.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationControls.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationControls.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; + +/** + * a collection of controls for annotations. + * allows selection of colors, shapes, etc + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class AnnotationControls { + + protected AnnotatingGraphMousePlugin annotatingPlugin; + + public AnnotationControls(AnnotatingGraphMousePlugin annotatingPlugin) { + this.annotatingPlugin = annotatingPlugin; + } + + @SuppressWarnings("serial") + public JComboBox getShapeBox() { + JComboBox shapeBox = new JComboBox( + new Shape[] { + new Rectangle2D.Double(), + new RoundRectangle2D.Double(0,0,0,0,50,50), + new Ellipse2D.Double() + }); + shapeBox.setRenderer(new DefaultListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean hasFocus) { + String valueString = value.toString(); + valueString = valueString.substring(0,valueString.indexOf("2D")); + valueString = valueString.substring(valueString.lastIndexOf('.')+1); + return super.getListCellRendererComponent(list, valueString, index, + isSelected, hasFocus); + } + }); + shapeBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + annotatingPlugin.setRectangularShape((RectangularShape)e.getItem()); + } + + }}); + return shapeBox; + } + + public JButton getColorChooserButton() { + final JButton colorChooser = new JButton("Color"); + colorChooser.setForeground(annotatingPlugin.getAnnotationColor()); + colorChooser.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + Color color = JColorChooser.showDialog(colorChooser, "Annotation Color", + colorChooser.getForeground()); + annotatingPlugin.setAnnotationColor(color); + colorChooser.setForeground(color); + }}); + return colorChooser; + } + + public JComboBox getLayerBox() { + final JComboBox layerBox = new JComboBox( + new Annotation.Layer[] { + Annotation.Layer.LOWER, Annotation.Layer.UPPER + }); + layerBox.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + annotatingPlugin.setLayer((Annotation.Layer)e.getItem()); + } + + }}); + + return layerBox; + } + + public JToggleButton getFillButton() { + JToggleButton fillButton = new JToggleButton("Fill"); + fillButton.addItemListener(new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + annotatingPlugin.setFill(e.getStateChange() == ItemEvent.SELECTED); + + }}); + return fillButton; + } + + public JToolBar getAnnotationsToolBar() { + JToolBar toolBar = new JToolBar(); + toolBar.add(this.getShapeBox()); + toolBar.add(this.getColorChooserButton()); + toolBar.add(this.getFillButton()); + toolBar.add(this.getLayerBox()); + return toolBar; + + } + + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/Annotation.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/Annotation.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/Annotation.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/Annotation.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Paint; +import java.awt.geom.Point2D; + +/** + * stores an annotation, either a shape or a string + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the type of the annotation object + */ +public class Annotation { + + protected T annotation; + protected Paint paint; + protected Point2D location; + protected Layer layer; + protected boolean fill; + public static enum Layer { LOWER, UPPER } + + public Annotation(T annotation, Layer layer, Paint paint, + boolean fill, Point2D location) { + this.annotation = annotation; + this.layer = layer; + this.paint = paint; + this.fill = fill; + this.location = location; + } + /** + * @return the annotation + */ + public T getAnnotation() { + return annotation; + } + /** + * @param annotation the annotation to set + */ + public void setAnnotation(T annotation) { + this.annotation = annotation; + } + /** + * @return the location + */ + public Point2D getLocation() { + return location; + } + /** + * @return the layer + */ + public Layer getLayer() { + return layer; + } + /** + * @param layer the layer to set + */ + public void setLayer(Layer layer) { + this.layer = layer; + } + /** + * @param location the location to set + */ + public void setLocation(Point2D location) { + this.location = location; + } + /** + * @return the paint + */ + public Paint getPaint() { + return paint; + } + /** + * @param paint the paint to set + */ + public void setPaint(Paint paint) { + this.paint = paint; + } + /** + * @return the fill + */ + public boolean isFill() { + return fill; + } + /** + * @param fill the fill to set + */ + public void setFill(boolean fill) { + this.fill = fill; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationManager.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationManager.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationManager.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationManager.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.AffineTransformer; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * handles the selection of annotations, and the support for the + * tools to draw them at specific layers. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class AnnotationManager { + + protected AnnotationRenderer annotationRenderer = new AnnotationRenderer(); + protected AnnotationPaintable lowerAnnotationPaintable; + protected AnnotationPaintable upperAnnotationPaintable; + + protected RenderContext rc; + protected AffineTransformer transformer; + + public AnnotationManager(RenderContext rc) { + this.rc = rc; + this.lowerAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer); + this.upperAnnotationPaintable = new AnnotationPaintable(rc, annotationRenderer); + + MutableTransformer mt = rc.getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + if(mt instanceof AffineTransformer) { + transformer = (AffineTransformer)mt; + } else if(mt instanceof LensTransformer) { + transformer = (AffineTransformer)((LensTransformer)mt).getDelegate(); + } + + } + + public AnnotationPaintable getAnnotationPaintable(Annotation.Layer layer) { + if(layer == Annotation.Layer.LOWER) { + return this.lowerAnnotationPaintable; + } + if(layer == Annotation.Layer.UPPER) { + return this.upperAnnotationPaintable; + } + return null; + } + + public void add(Annotation.Layer layer, Annotation annotation) { + if(layer == Annotation.Layer.LOWER) { + this.lowerAnnotationPaintable.add(annotation); + } + if(layer == Annotation.Layer.UPPER) { + this.upperAnnotationPaintable.add(annotation); + } + } + + public void remove(Annotation annotation) { + this.lowerAnnotationPaintable.remove(annotation); + this.upperAnnotationPaintable.remove(annotation); + } + + protected AnnotationPaintable getLowerAnnotationPaintable() { + return lowerAnnotationPaintable; + } + + protected AnnotationPaintable getUpperAnnotationPaintable() { + return upperAnnotationPaintable; + } + + public Annotation getAnnotation(Point2D p) { + @SuppressWarnings("rawtypes") + Set annotations = new HashSet(lowerAnnotationPaintable.getAnnotations()); + annotations.addAll(upperAnnotationPaintable.getAnnotations()); + return getAnnotation(p, annotations); + } + + @SuppressWarnings("rawtypes") + public Annotation getAnnotation(Point2D p, Collection annotations) { + double closestDistance = Double.MAX_VALUE; + Annotation closestAnnotation = null; + for(Annotation annotation : annotations) { + Object ann = annotation.getAnnotation(); + if(ann instanceof Shape) { + Point2D ip = rc.getMultiLayerTransformer().inverseTransform(p); + Shape shape = (Shape)ann; + if(shape.contains(ip)) { + + Rectangle2D shapeBounds = shape.getBounds2D(); + Point2D shapeCenter = new Point2D.Double(shapeBounds.getCenterX(), shapeBounds.getCenterY()); + double distanceSq = shapeCenter.distanceSq(ip); + if(distanceSq < closestDistance) { + closestDistance = distanceSq; + closestAnnotation = annotation; + } + } + } else if(ann instanceof String) { + + Point2D ip = rc.getMultiLayerTransformer().inverseTransform(Layer.VIEW, p); + Point2D ap = annotation.getLocation(); + String label = (String)ann; + Component component = prepareRenderer(rc, annotationRenderer, label); + + AffineTransform base = new AffineTransform(transformer.getTransform()); + double rotation = transformer.getRotation(); + // unrotate the annotation + AffineTransform unrotate = + AffineTransform.getRotateInstance(-rotation, ap.getX(), ap.getY()); + base.concatenate(unrotate); + + Dimension d = component.getPreferredSize(); + Rectangle2D componentBounds = new Rectangle2D.Double(ap.getX(), ap.getY(), d.width, d.height); + + Shape componentBoundsShape = base.createTransformedShape(componentBounds); + Point2D componentCenter = new Point2D.Double(componentBoundsShape.getBounds().getCenterX(), + componentBoundsShape.getBounds().getCenterY()); + if(componentBoundsShape.contains(ip)) { + double distanceSq = componentCenter.distanceSq(ip); + if(distanceSq < closestDistance) { + closestDistance = distanceSq; + closestAnnotation = annotation; + } + } + + } + } + return closestAnnotation; + } + + public Component prepareRenderer(RenderContext rc, AnnotationRenderer annotationRenderer, Object value) { + return annotationRenderer.getAnnotationRendererComponent(rc.getScreenDevice(), value); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationPaintable.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationPaintable.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationPaintable.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationPaintable.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.transform.AffineTransformer; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * handles the actual drawing of annotations + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class AnnotationPaintable implements Paintable { + + @SuppressWarnings("rawtypes") + protected Set annotations = new HashSet(); + protected AnnotationRenderer annotationRenderer; + + protected RenderContext rc; + protected AffineTransformer transformer; + + public AnnotationPaintable(RenderContext rc, AnnotationRenderer annotationRenderer) { + this.rc = rc; + this.annotationRenderer = annotationRenderer; + MutableTransformer mt = rc.getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + if(mt instanceof AffineTransformer) { + transformer = (AffineTransformer)mt; + } else if(mt instanceof LensTransformer) { + transformer = (AffineTransformer)((LensTransformer)mt).getDelegate(); + } + } + + public void add(Annotation annotation) { + annotations.add(annotation); + } + + public void remove(Annotation annotation) { + annotations.remove(annotation); + } + + /** + * @return the annotations + */ + @SuppressWarnings("rawtypes") + public Set getAnnotations() { + return Collections.unmodifiableSet(annotations); + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + Color oldColor = g.getColor(); + for(Annotation annotation : annotations) { + Object ann = annotation.getAnnotation(); + if(ann instanceof Shape) { + Shape shape = (Shape)ann; + Paint paint = annotation.getPaint(); + Shape s = transformer.transform(shape); + g2d.setPaint(paint); + if(annotation.isFill()) { + g2d.fill(s); + } else { + g2d.draw(s); + } + } else if(ann instanceof String) { + Point2D p = annotation.getLocation(); + String label = (String)ann; + Component component = prepareRenderer(rc, annotationRenderer, label); + component.setForeground((Color)annotation.getPaint()); + if(annotation.isFill()) { + ((JComponent)component).setOpaque(true); + component.setBackground((Color)annotation.getPaint()); + component.setForeground(Color.black); + } + Dimension d = component.getPreferredSize(); + AffineTransform old = g2d.getTransform(); + AffineTransform base = new AffineTransform(old); + AffineTransform xform = transformer.getTransform(); + + double rotation = transformer.getRotation(); + // unrotate the annotation + AffineTransform unrotate = + AffineTransform.getRotateInstance(-rotation, p.getX(), p.getY()); + base.concatenate(xform); + base.concatenate(unrotate); + g2d.setTransform(base); + rc.getRendererPane().paintComponent(g, component, rc.getScreenDevice(), + (int)p.getX(), (int)p.getY(), + d.width, d.height, true); + g2d.setTransform(old); + } + } + g.setColor(oldColor); + } + + public Component prepareRenderer(RenderContext rc, AnnotationRenderer annotationRenderer, Object value) { + return annotationRenderer.getAnnotationRendererComponent(rc.getScreenDevice(), value); + } + + public boolean useTransform() { + return true; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/AnnotationRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ + +package edu.uci.ics.jung.visualization.annotations; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * AnnotationRenderer is similar to the cell renderers + * used by the JTable and JTree JFC classes. + * + * @author Tom Nelson + * + * + */ +@SuppressWarnings("serial") +public class AnnotationRenderer extends JLabel implements + Serializable { + + protected static Border noFocusBorder = new EmptyBorder(0,0,0,0); + + /** + * Creates a default table cell renderer. + */ + public AnnotationRenderer() { + setOpaque(true); + setBorder(noFocusBorder); + } + + /** + * Overrides JComponent.setForeground to assign + * the unselected-foreground color to the specified color. + * + * @param c set the foreground color to this value + */ + @Override + public void setForeground(Color c) { + super.setForeground(c); + } + + /** + * Overrides JComponent.setBackground to assign + * the unselected-background color to the specified color. + * + * @param c set the background color to this value + */ + @Override + public void setBackground(Color c) { + super.setBackground(c); + } + + /** + * Notification from the UIManager that the look and feel + * has changed. + * Replaces the current UI object with the latest version from the + * UIManager. + * + * @see JComponent#updateUI + */ + @Override + public void updateUI() { + super.updateUI(); + setForeground(null); + setBackground(null); + } + + /** + * Returns the default label renderer. + * + * @param vv the VisualizationViewer to render on + * @param value the value to assign to the label + * @return the default label renderer + */ + public Component getAnnotationRendererComponent(JComponent vv, Object value) { + + super.setForeground(vv.getForeground()); + super.setBackground(vv.getBackground()); + + setFont(vv.getFont()); + setIcon(null); + setBorder(noFocusBorder); + setValue(value); + return this; + } + + /* + * The following methods are overridden as a performance measure to + * to prune code-paths are often called in the case of renders + * but which we know are unnecessary. Great care should be taken + * when writing your own renderer to weigh the benefits and + * drawbacks of overriding methods like these. + */ + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public boolean isOpaque() { + Color back = getBackground(); + Component p = getParent(); + if (p != null) { + p = p.getParent(); + } + boolean colorMatch = (back != null) && (p != null) && + back.equals(p.getBackground()) && + p.isOpaque(); + return !colorMatch && super.isOpaque(); + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void validate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void revalidate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(long tm, int x, int y, int width, int height) {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(Rectangle r) { } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + // Strings get interned... + if (propertyName=="text") { + super.firePropertyChange(propertyName, oldValue, newValue); + } + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { } + + /** + * Sets the String object for the cell being rendered to + * value. + * + * @param value the string value for this cell; if value is + * null it sets the text value to an empty string + * @see JLabel#setText + * + */ + protected void setValue(Object value) { + setText((value == null) ? "" : value.toString()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/annotations/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Classes which support creating visual annotations for graphs. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,173 @@ +package edu.uci.ics.jung.visualization; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; +import edu.uci.ics.jung.visualization.util.DefaultChangeEventSupport; + +/** + * A basic implementation of the MultiLayerTransformer interface that + * provides two Layers: VIEW and LAYOUT. It also provides ChangeEventSupport + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class BasicTransformer implements MultiLayerTransformer, + ShapeTransformer, ChangeListener, ChangeEventSupport { + + protected ChangeEventSupport changeSupport = + new DefaultChangeEventSupport(this); + + protected MutableTransformer viewTransformer = + new MutableAffineTransformer(new AffineTransform()); + + protected MutableTransformer layoutTransformer = + new MutableAffineTransformer(new AffineTransform()); + + /** + * Creates an instance and notifies the view and layout Functions to listen to + * changes published by this instance. + */ + public BasicTransformer() { + super(); + viewTransformer.addChangeListener(this); + layoutTransformer.addChangeListener(this); + } + + protected void setViewTransformer(MutableTransformer Function) { + this.viewTransformer.removeChangeListener(this); + this.viewTransformer = Function; + this.viewTransformer.addChangeListener(this); + } + + protected void setLayoutTransformer(MutableTransformer Function) { + this.layoutTransformer.removeChangeListener(this); + this.layoutTransformer = Function; + this.layoutTransformer.addChangeListener(this); + } + + + protected MutableTransformer getLayoutTransformer() { + return layoutTransformer; + } + + protected MutableTransformer getViewTransformer() { + return viewTransformer; + } + + public Point2D inverseTransform(Point2D p) { + return inverseLayoutTransform(inverseViewTransform(p)); + } + + protected Point2D inverseViewTransform(Point2D p) { + return viewTransformer.inverseTransform(p); + } + + protected Point2D inverseLayoutTransform(Point2D p) { + return layoutTransformer.inverseTransform(p); + } + + public Point2D transform(Point2D p) { + return viewTransform(layoutTransform(p)); + } + + protected Point2D viewTransform(Point2D p) { + return viewTransformer.transform(p); + } + + protected Point2D layoutTransform(Point2D p) { + return layoutTransformer.transform(p); + } + + public Shape inverseTransform(Shape shape) { + return inverseLayoutTransform(inverseViewTransform(shape)); + } + + protected Shape inverseViewTransform(Shape shape) { + return viewTransformer.inverseTransform(shape); + } + + protected Shape inverseLayoutTransform(Shape shape) { + return layoutTransformer.inverseTransform(shape); + } + + public Shape transform(Shape shape) { + return viewTransform(layoutTransform(shape)); + } + + protected Shape viewTransform(Shape shape) { + return viewTransformer.transform(shape); + } + + protected Shape layoutTransform(Shape shape) { + return layoutTransformer.transform(shape); + } + + public void setToIdentity() { + layoutTransformer.setToIdentity(); + viewTransformer.setToIdentity(); + } + + public void addChangeListener(ChangeListener l) { + changeSupport.addChangeListener(l); + } + + public void removeChangeListener(ChangeListener l) { + changeSupport.removeChangeListener(l); + } + + public ChangeListener[] getChangeListeners() { + return changeSupport.getChangeListeners(); + } + + public void fireStateChanged() { + changeSupport.fireStateChanged(); + } + + public void stateChanged(ChangeEvent e) { + fireStateChanged(); + } + + public MutableTransformer getTransformer(Layer layer) { + if(layer == Layer.LAYOUT) return layoutTransformer; + if(layer == Layer.VIEW) return viewTransformer; + return null; + } + + public Point2D inverseTransform(Layer layer, Point2D p) { + if(layer == Layer.LAYOUT) return inverseLayoutTransform(p); + if(layer == Layer.VIEW) return inverseViewTransform(p); + return null; + } + + public void setTransformer(Layer layer, MutableTransformer Function) { + if(layer == Layer.LAYOUT) setLayoutTransformer(Function); + if(layer == Layer.VIEW) setViewTransformer(Function); + + } + + public Point2D transform(Layer layer, Point2D p) { + if(layer == Layer.LAYOUT) return layoutTransform(p); + if(layer == Layer.VIEW) return viewTransform(p); + return null; + } + + public Shape transform(Layer layer, Shape shape) { + if(layer == Layer.LAYOUT) return layoutTransform(shape); + if(layer == Layer.VIEW) return viewTransform(shape); + return null; + } + + public Shape inverseTransform(Layer layer, Shape shape) { + if(layer == Layer.LAYOUT) return inverseLayoutTransform(shape); + if(layer == Layer.VIEW) return inverseViewTransform(shape); + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicVisualizationServer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicVisualizationServer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicVisualizationServer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/BasicVisualizationServer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,508 @@ +/* +\* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.control.ScalingControl; +import edu.uci.ics.jung.visualization.decorators.PickableEdgePaintTransformer; +import edu.uci.ics.jung.visualization.decorators.PickableVertexPaintTransformer; +import edu.uci.ics.jung.visualization.picking.MultiPickedState; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.picking.ShapePickSupport; +import edu.uci.ics.jung.visualization.renderers.BasicRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; +import edu.uci.ics.jung.visualization.util.Caching; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; +import edu.uci.ics.jung.visualization.util.DefaultChangeEventSupport; + +/** + * A class that maintains many of the details necessary for creating + * visualizations of graphs. + * This is the old VisualizationViewer without tooltips and mouse behaviors. Its purpose is + * to be a base class that can also be used on the server side of a multi-tiered application. + * + * @author Joshua O'Madadhain + * @author Tom Nelson + * @author Danyel Fisher + */ +@SuppressWarnings("serial") +public class BasicVisualizationServer extends JPanel + implements ChangeListener, ChangeEventSupport, VisualizationServer{ + + protected ChangeEventSupport changeSupport = + new DefaultChangeEventSupport(this); + + /** + * holds the state of this View + */ + protected VisualizationModel model; + + /** + * handles the actual drawing of graph elements + */ + protected Renderer renderer = new BasicRenderer(); + + /** + * rendering hints used in drawing. Anti-aliasing is on + * by default + */ + protected Map renderingHints = new HashMap(); + + /** + * holds the state of which vertices of the graph are + * currently 'picked' + */ + protected PickedState pickedVertexState; + + /** + * holds the state of which edges of the graph are + * currently 'picked' + */ + protected PickedState pickedEdgeState; + + /** + * a listener used to cause pick events to result in + * repaints, even if they come from another view + */ + protected ItemListener pickEventListener; + + /** + * an offscreen image to render the graph + * Used if doubleBuffered is set to true + */ + protected BufferedImage offscreen; + + /** + * graphics context for the offscreen image + * Used if doubleBuffered is set to true + */ + protected Graphics2D offscreenG2d; + + /** + * user-settable choice to use the offscreen image + * or not. 'false' by default + */ + protected boolean doubleBuffered; + + /** + * a collection of user-implementable functions to render under + * the topology (before the graph is rendered) + */ + protected List preRenderers = new ArrayList(); + + /** + * a collection of user-implementable functions to render over the + * topology (after the graph is rendered) + */ + protected List postRenderers = new ArrayList(); + + protected RenderContext renderContext; + + /** + * Create an instance with the specified Layout. + * + * @param layout The Layout to apply, with its associated Graph + */ + public BasicVisualizationServer(Layout layout) { + this(new DefaultVisualizationModel(layout)); + } + + /** + * Create an instance with the specified Layout and view dimension. + * + * @param layout The Layout to apply, with its associated Graph + * @param preferredSize the preferred size of this View + */ + public BasicVisualizationServer(Layout layout, Dimension preferredSize) { + this(new DefaultVisualizationModel(layout, preferredSize), preferredSize); + } + + /** + * Create an instance with the specified model and a default dimension (600x600). + * + * @param model the model to use + */ + public BasicVisualizationServer(VisualizationModel model) { + this(model, new Dimension(600,600)); + } + + /** + * Create an instance with the specified model and view dimension. + * + * @param model the model to use + * @param preferredSize initial preferred size of the view + */ + public BasicVisualizationServer(VisualizationModel model, + Dimension preferredSize) { + this.model = model; + renderContext = new PluggableRenderContext(model.getGraphLayout().getGraph()); + model.addChangeListener(this); + setDoubleBuffered(false); + this.addComponentListener(new VisualizationListener(this)); + + setPickSupport(new ShapePickSupport(this)); + setPickedVertexState(new MultiPickedState()); + setPickedEdgeState(new MultiPickedState()); + + renderContext.setEdgeDrawPaintTransformer(new PickableEdgePaintTransformer(getPickedEdgeState(), Color.black, Color.cyan)); + renderContext.setVertexFillPaintTransformer(new PickableVertexPaintTransformer(getPickedVertexState(), + Color.red, Color.yellow)); + + setPreferredSize(preferredSize); + renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + renderContext.getMultiLayerTransformer().addChangeListener(this); + } + + @Override + public void setDoubleBuffered(boolean doubleBuffered) { + this.doubleBuffered = doubleBuffered; + } + + @Override + public boolean isDoubleBuffered() { + return doubleBuffered; + } + + /** + * Always sanity-check getSize so that we don't use a + * value that is improbable + * @see java.awt.Component#getSize() + */ + @Override + public Dimension getSize() { + Dimension d = super.getSize(); + if(d.width <= 0 || d.height <= 0) { + d = getPreferredSize(); + } + return d; + } + + /** + * Ensure that, if doubleBuffering is enabled, the offscreen + * image buffer exists and is the correct size. + * @param d the expected Dimension of the offscreen buffer + */ + protected void checkOffscreenImage(Dimension d) { + if(doubleBuffered) { + if(offscreen == null || offscreen.getWidth() != d.width || offscreen.getHeight() != d.height) { + offscreen = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB); + offscreenG2d = offscreen.createGraphics(); + } + } + } + + public VisualizationModel getModel() { + return model; + } + + public void setModel(VisualizationModel model) { + this.model = model; + } + + public void stateChanged(ChangeEvent e) { + repaint(); + fireStateChanged(); + } + + public void setRenderer(Renderer r) { + this.renderer = r; + repaint(); + } + + public Renderer getRenderer() { + return renderer; + } + + public void setGraphLayout(Layout layout) { + Dimension viewSize = getPreferredSize(); + if(this.isShowing()) { + viewSize = getSize(); + } + model.setGraphLayout(layout, viewSize); + } + + public void scaleToLayout(ScalingControl scaler) { + Dimension vd = getPreferredSize(); + if(this.isShowing()) { + vd = getSize(); + } + Dimension ld = getGraphLayout().getSize(); + if(vd.equals(ld) == false) { + scaler.scale(this, (float)(vd.getWidth()/ld.getWidth()), new Point2D.Double()); + } + } + + public Layout getGraphLayout() { + return model.getGraphLayout(); + } + + @Override + public void setVisible(boolean aFlag) { + super.setVisible(aFlag); + if(aFlag == true) { + Dimension d = this.getSize(); + if(d.width <= 0 || d.height <= 0) { + d = this.getPreferredSize(); + } + model.getGraphLayout().setSize(d); + } + } + + public Map getRenderingHints() { + return renderingHints; + } + + public void setRenderingHints(Map renderingHints) { + this.renderingHints = renderingHints; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + Graphics2D g2d = (Graphics2D)g; + if(doubleBuffered) { + checkOffscreenImage(getSize()); + renderGraph(offscreenG2d); + g2d.drawImage(offscreen, null, 0, 0); + } else { + renderGraph(g2d); + } + } + + protected void renderGraph(Graphics2D g2d) { + if(renderContext.getGraphicsContext() == null) { + renderContext.setGraphicsContext(new GraphicsDecorator(g2d)); + } else { + renderContext.getGraphicsContext().setDelegate(g2d); + } + renderContext.setScreenDevice(this); + Layout layout = model.getGraphLayout(); + + g2d.setRenderingHints(renderingHints); + + // the size of the VisualizationViewer + Dimension d = getSize(); + + // clear the offscreen image + g2d.setColor(getBackground()); + g2d.fillRect(0,0,d.width,d.height); + + AffineTransform oldXform = g2d.getTransform(); + AffineTransform newXform = new AffineTransform(oldXform); + newXform.concatenate( + renderContext.getMultiLayerTransformer().getTransformer(Layer.VIEW).getTransform()); + + g2d.setTransform(newXform); + + // if there are preRenderers set, paint them + for(Paintable paintable : preRenderers) { + + if(paintable.useTransform()) { + paintable.paint(g2d); + } else { + g2d.setTransform(oldXform); + paintable.paint(g2d); + g2d.setTransform(newXform); + } + } + + if(layout instanceof Caching) { + ((Caching)layout).clear(); + } + + renderer.render(renderContext, layout); + + // if there are postRenderers set, do it + for(Paintable paintable : postRenderers) { + + if(paintable.useTransform()) { + paintable.paint(g2d); + } else { + g2d.setTransform(oldXform); + paintable.paint(g2d); + g2d.setTransform(newXform); + } + } + g2d.setTransform(oldXform); + } + + /** + * VisualizationListener reacts to changes in the size of the + * VisualizationViewer. When the size changes, it ensures + * that the offscreen image is sized properly. + * If the layout is locked to this view size, then the layout + * is also resized to be the same as the view size. + * + * + */ + protected class VisualizationListener extends ComponentAdapter { + protected BasicVisualizationServer vv; + public VisualizationListener(BasicVisualizationServer vv) { + this.vv = vv; + } + + /** + * create a new offscreen image for the graph + * whenever the window is resied + */ + @Override + public void componentResized(ComponentEvent e) { + Dimension d = vv.getSize(); + if(d.width <= 0 || d.height <= 0) return; + checkOffscreenImage(d); + repaint(); + } + } + + public void addPreRenderPaintable(Paintable paintable) { + if(preRenderers == null) { + preRenderers = new ArrayList(); + } + preRenderers.add(paintable); + } + + public void prependPreRenderPaintable(Paintable paintable) { + if(preRenderers == null) { + preRenderers = new ArrayList(); + } + preRenderers.add(0,paintable); + } + + public void removePreRenderPaintable(Paintable paintable) { + if(preRenderers != null) { + preRenderers.remove(paintable); + } + } + + public void addPostRenderPaintable(Paintable paintable) { + if(postRenderers == null) { + postRenderers = new ArrayList(); + } + postRenderers.add(paintable); + } + + public void prependPostRenderPaintable(Paintable paintable) { + if(postRenderers == null) { + postRenderers = new ArrayList(); + } + postRenderers.add(0,paintable); + } + + public void removePostRenderPaintable(Paintable paintable) { + if(postRenderers != null) { + postRenderers.remove(paintable); + } + } + + public void addChangeListener(ChangeListener l) { + changeSupport.addChangeListener(l); + } + + public void removeChangeListener(ChangeListener l) { + changeSupport.removeChangeListener(l); + } + + public ChangeListener[] getChangeListeners() { + return changeSupport.getChangeListeners(); + } + + public void fireStateChanged() { + changeSupport.fireStateChanged(); + } + + public PickedState getPickedVertexState() { + return pickedVertexState; + } + + public PickedState getPickedEdgeState() { + return pickedEdgeState; + } + + public void setPickedVertexState(PickedState pickedVertexState) { + if(pickEventListener != null && this.pickedVertexState != null) { + this.pickedVertexState.removeItemListener(pickEventListener); + } + this.pickedVertexState = pickedVertexState; + this.renderContext.setPickedVertexState(pickedVertexState); + if(pickEventListener == null) { + pickEventListener = new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + repaint(); + } + }; + } + pickedVertexState.addItemListener(pickEventListener); + } + + public void setPickedEdgeState(PickedState pickedEdgeState) { + if(pickEventListener != null && this.pickedEdgeState != null) { + this.pickedEdgeState.removeItemListener(pickEventListener); + } + this.pickedEdgeState = pickedEdgeState; + this.renderContext.setPickedEdgeState(pickedEdgeState); + if(pickEventListener == null) { + pickEventListener = new ItemListener() { + + public void itemStateChanged(ItemEvent e) { + repaint(); + } + }; + } + pickedEdgeState.addItemListener(pickEventListener); + } + + public GraphElementAccessor getPickSupport() { + return renderContext.getPickSupport(); + } + + public void setPickSupport(GraphElementAccessor pickSupport) { + renderContext.setPickSupport(pickSupport); + } + + public Point2D getCenter() { + Dimension d = getSize(); + return new Point2D.Float(d.width/2, d.height/2); + } + + public RenderContext getRenderContext() { + return renderContext; + } + + public void setRenderContext(RenderContext renderContext) { + this.renderContext = renderContext; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbsoluteCrossoverScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbsoluteCrossoverScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbsoluteCrossoverScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbsoluteCrossoverScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Scales to the absolute value passed as an argument. + * It first resets the scaling Functions, then uses + * the relative CrossoverScalingControl to achieve the + * absolute value. + * + * @author Tom Nelson + * + */ +public class AbsoluteCrossoverScalingControl extends CrossoverScalingControl + implements ScalingControl { + + /** + * Scale to the absolute value passed as 'amount'. + * + * @param vv the VisualizationServer used for rendering; provides the layout and view transformers. + * @param amount the amount by which to scale + * @param at the point of reference for scaling + */ + public void scale(VisualizationServer vv, float amount, Point2D at) { + MutableTransformer layoutTransformer + = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + MutableTransformer viewTransformer + = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + double modelScale = layoutTransformer.getScale(); + double viewScale = viewTransformer.getScale(); + double inverseModelScale = Math.sqrt(crossover)/modelScale; + double inverseViewScale = Math.sqrt(crossover)/viewScale; + + Point2D transformedAt + = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, at); + + // return the Functions to 1.0 + layoutTransformer.scale(inverseModelScale, inverseModelScale, transformedAt); + viewTransformer.scale(inverseViewScale, inverseViewScale, at); + + super.scale(vv, amount, at); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 6, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.Point; +import java.awt.event.MouseEvent; + +/** + * a base class for GraphMousePlugin instances. Holds some members + * common to all GraphMousePlugins + * @author thomasnelson + * + */ +public abstract class AbstractGraphMousePlugin implements GraphMousePlugin { + + /** + * modifiers to compare against mouse event modifiers + */ + protected int modifiers; + + /** + * the location in the View where the mouse was pressed + */ + protected Point down; + + /** + * the special cursor that plugins may display + */ + protected Cursor cursor; + + /** + * Creates an instance with the specified mouse event modifiers. + * @param modifiers the mouse event modifiers to use + */ + public AbstractGraphMousePlugin(int modifiers) { + this.modifiers = modifiers; + } + + /** + * getter for mouse modifiers + */ + public int getModifiers() { + return modifiers; + } + + /** + * setter for mouse modifiers + */ + public void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + /** + * check the mouse event modifiers against the + * instance member modifiers. Default implementation + * checks equality. Can be overridden to test with a mask + */ + public boolean checkModifiers(MouseEvent e) { + return e.getModifiers() == modifiers; + } + + /** + * @return Returns the cursor. + */ + public Cursor getCursor() { + return cursor; + } + + /** + * @param cursor The cursor to set. + */ + public void setCursor(Cursor cursor) { + this.cursor = cursor; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractModalGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractModalGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractModalGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractModalGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Dimension; +import java.awt.ItemSelectable; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyListener; + +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.event.EventListenerList; +import javax.swing.plaf.basic.BasicIconFactory; + + +/** + * + * AbstractModalGraphMouse is a PluggableGraphMouse class that + * manages a collection of plugins for picking and + * transforming the graph. Additionally, it carries the notion + * of a Mode: Picking or Translating. Switching between modes + * allows for a more natural choice of mouse modifiers to + * be used for the various plugins. The default modifiers are + * intended to mimick those of mainstream software applications + * in order to be intuitive to users. + * + * To change between modes, two different controls are offered, + * a combo box and a menu system. These controls are lazily created + * in their respective 'getter' methods so they don't impact + * code that does not intend to use them. + * The menu control can be placed in an unused corner of the + * GraphZoomScrollPane, which is a common location for mouse + * mode selection menus in mainstream applications. + * + * Users must implement the loadPlugins() method to create and + * install the GraphMousePlugins. The order of the plugins is + * important, as they are evaluated against the mask parameters + * in the order that they are added. + * + * @author Tom Nelson + */ +public abstract class AbstractModalGraphMouse extends PluggableGraphMouse + implements ModalGraphMouse, ItemSelectable { + + /** + * used by the scaling plugins for zoom in + */ + protected float in; + /** + * used by the scaling plugins for zoom out + */ + protected float out; + /** + * a listener for mode changes + */ + protected ItemListener modeListener; + /** + * a JComboBox control available to set the mode + */ + protected JComboBox modeBox; + /** + * a menu available to set the mode + */ + protected JMenu modeMenu; + /** + * the current mode + */ + protected Mode mode; + /** + * listeners for mode changes + */ + protected EventListenerList listenerList = new EventListenerList(); + + protected GraphMousePlugin pickingPlugin; + protected GraphMousePlugin translatingPlugin; + protected GraphMousePlugin animatedPickingPlugin; + protected GraphMousePlugin scalingPlugin; + protected GraphMousePlugin rotatingPlugin; + protected GraphMousePlugin shearingPlugin; + protected KeyListener modeKeyListener; + + + protected AbstractModalGraphMouse(float in, float out) { + this.in = in; + this.out = out; + } + + /** + * create the plugins, and load the plugins for TRANSFORMING mode + * + */ + protected abstract void loadPlugins(); + + /** + * setter for the Mode. + */ + public void setMode(Mode mode) { + if(this.mode != mode) { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + this.mode, ItemEvent.DESELECTED)); + this.mode = mode; + if(mode == Mode.TRANSFORMING) { + setTransformingMode(); + } else if(mode == Mode.PICKING) { + setPickingMode(); + } + if(modeBox != null) { + modeBox.setSelectedItem(mode); + } + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, mode, ItemEvent.SELECTED)); + } + } + /* (non-Javadoc) + * @see edu.uci.ics.jung.visualization.control.ModalGraphMouse#setPickingMode() + */ + protected void setPickingMode() { + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + add(pickingPlugin); + add(animatedPickingPlugin); + } + + /* (non-Javadoc) + * @see edu.uci.ics.jung.visualization.control.ModalGraphMouse#setTransformingMode() + */ + protected void setTransformingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + add(translatingPlugin); + add(rotatingPlugin); + add(shearingPlugin); + } + + /** + * @param zoomAtMouse The zoomAtMouse to set. + */ + public void setZoomAtMouse(boolean zoomAtMouse) { + ((ScalingGraphMousePlugin) scalingPlugin).setZoomAtMouse(zoomAtMouse); + } + + /** + * listener to set the mode from an external event source + */ + class ModeListener implements ItemListener { + public void itemStateChanged(ItemEvent e) { + setMode((Mode) e.getItem()); + } + } + + /* (non-Javadoc) + * @see edu.uci.ics.jung.visualization.control.ModalGraphMouse#getModeListener() + */ + public ItemListener getModeListener() { + if (modeListener == null) { + modeListener = new ModeListener(); + } + return modeListener; + } + + /** + * @return the modeKeyListener + */ + public KeyListener getModeKeyListener() { + return modeKeyListener; + } + + /** + * @param modeKeyListener the modeKeyListener to set + */ + public void setModeKeyListener(KeyListener modeKeyListener) { + this.modeKeyListener = modeKeyListener; + } + + /** + * @return Returns the modeBox. + */ + public JComboBox getModeComboBox() { + if(modeBox == null) { + modeBox = new JComboBox(new Mode[]{Mode.TRANSFORMING, Mode.PICKING}); + modeBox.addItemListener(getModeListener()); + } + modeBox.setSelectedItem(mode); + return modeBox; + } + + /** + * create (if necessary) and return a menu that will change + * the mode + * @return the menu + */ + public JMenu getModeMenu() { + if(modeMenu == null) { + modeMenu = new JMenu();// { + Icon icon = BasicIconFactory.getMenuArrowIcon(); + modeMenu.setIcon(BasicIconFactory.getMenuArrowIcon()); + modeMenu.setPreferredSize(new Dimension(icon.getIconWidth()+10, + icon.getIconHeight()+10)); + + final JRadioButtonMenuItem transformingButton = + new JRadioButtonMenuItem(Mode.TRANSFORMING.toString()); + transformingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.TRANSFORMING); + } + }}); + + final JRadioButtonMenuItem pickingButton = + new JRadioButtonMenuItem(Mode.PICKING.toString()); + pickingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.PICKING); + } + }}); + ButtonGroup radio = new ButtonGroup(); + radio.add(transformingButton); + radio.add(pickingButton); + transformingButton.setSelected(true); + modeMenu.add(transformingButton); + modeMenu.add(pickingButton); + modeMenu.setToolTipText("Menu for setting Mouse Mode"); + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + if(e.getItem() == Mode.TRANSFORMING) { + transformingButton.setSelected(true); + } else if(e.getItem() == Mode.PICKING) { + pickingButton.setSelected(true); + } + } + }}); + } + return modeMenu; + } + + /** + * add a listener for mode changes + */ + public void addItemListener(ItemListener aListener) { + listenerList.add(ItemListener.class,aListener); + } + + /** + * remove a listener for mode changes + */ + public void removeItemListener(ItemListener aListener) { + listenerList.remove(ItemListener.class,aListener); + } + + /** + * Returns an array of all the ItemListeners added + * to this JComboBox with addItemListener(). + * + * @return all of the ItemListeners added or an empty + * array if no listeners have been added + * @since 1.4 + */ + public ItemListener[] getItemListeners() { + return listenerList.getListeners(ItemListener.class); + } + + public Object[] getSelectedObjects() { + if ( mode == null ) + return new Object[0]; + else { + Object result[] = new Object[1]; + result[0] = mode; + return result; + } + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. + * @param e the event of interest + * + * @see EventListenerList + */ + protected void fireItemStateChanged(ItemEvent e) { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for ( int i = listeners.length-2; i>=0; i-=2 ) { + if ( listeners[i]==ItemListener.class ) { + ((ItemListener)listeners[i+1]).itemStateChanged(e); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractPopupGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractPopupGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractPopupGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AbstractPopupGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +public abstract class AbstractPopupGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener { + + public AbstractPopupGraphMousePlugin() { + this(MouseEvent.BUTTON3_MASK); + } + public AbstractPopupGraphMousePlugin(int modifiers) { + super(modifiers); + } + public void mousePressed(MouseEvent e) { + if(e.isPopupTrigger()) { + handlePopup(e); + e.consume(); + } + } + + /** + * if this is the popup trigger, process here, otherwise + * defer to the superclass + */ + public void mouseReleased(MouseEvent e) { + if(e.isPopupTrigger()) { + handlePopup(e); + e.consume(); + } + } + + protected abstract void handlePopup(MouseEvent e); + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AnimatedPickingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AnimatedPickingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AnimatedPickingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/AnimatedPickingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.picking.PickedState; + +/** + * AnimatedPickingGraphMousePlugin supports the picking of one Graph + * Vertex. When the mouse is released, the graph is translated so that + * the picked Vertex is moved to the center of the view. This translation + * is conducted in an animation Thread so that the graph slides to its + * new position + * + * @author Tom Nelson + */ +public class AnimatedPickingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + * the picked Vertex + */ + protected V vertex; + + /** + * Creates an instance with default modifiers of BUTTON1_MASK and CTRL_MASK + */ + public AnimatedPickingGraphMousePlugin() { + this(InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK); + } + + /** + * Creates an instance with the specified mouse event modifiers. + * @param selectionModifiers the mouse event modifiers to use. + */ + public AnimatedPickingGraphMousePlugin(int selectionModifiers) { + super(selectionModifiers); + this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + } + + /** + * If the event occurs on a Vertex, pick that single Vertex + * @param e the event + */ + @SuppressWarnings("unchecked") + public void mousePressed(MouseEvent e) { + if (e.getModifiers() == modifiers) { + VisualizationViewer vv = (VisualizationViewer) e.getSource(); + GraphElementAccessor pickSupport = vv.getPickSupport(); + PickedState pickedVertexState = vv.getPickedVertexState(); + Layout layout = vv.getGraphLayout(); + if (pickSupport != null && pickedVertexState != null) { + // p is the screen point for the mouse event + Point2D p = e.getPoint(); + vertex = pickSupport.getVertex(layout, p.getX(), p.getY()); + if (vertex != null) { + if (pickedVertexState.isPicked(vertex) == false) { + pickedVertexState.clear(); + pickedVertexState.pick(vertex, true); + } + } + } + e.consume(); + } + } + + +/** + * If a Vertex was picked in the mousePressed event, start a Thread + * to animate the translation of the graph so that the picked Vertex + * moves to the center of the view + * + * @param e the event + */ + @SuppressWarnings("unchecked") + public void mouseReleased(MouseEvent e) { + if (e.getModifiers() == modifiers) { + final VisualizationViewer vv = (VisualizationViewer) e.getSource(); + Point2D newCenter = null; + if (vertex != null) { + // center the picked vertex + Layout layout = vv.getGraphLayout(); + newCenter = layout.apply(vertex); + } else { + // they did not pick a vertex to center, so + // just center the graph + newCenter = vv.getCenter(); + } + Point2D lvc = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(vv.getCenter()); + final double dx = (lvc.getX() - newCenter.getX()) / 10; + final double dy = (lvc.getY() - newCenter.getY()) / 10; + + Runnable animator = new Runnable() { + + public void run() { + for (int i = 0; i < 10; i++) { + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).translate(dx, dy); + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + } + } + } + }; + Thread thread = new Thread(animator); + thread.start(); + } + } + + public void mouseClicked(MouseEvent e) { + } + + /** + * show a special cursor while the mouse is inside the window + */ + public void mouseEntered(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(cursor); + } + + /** + * revert to the default cursor when the mouse leaves this window + */ + public void mouseExited(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + public void mouseMoved(MouseEvent e) { + } + + public void mouseDragged(MouseEvent arg0) { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CrossoverScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CrossoverScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CrossoverScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CrossoverScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * A scaling control that has a crossover point. + * When the overall scale of the view and + * model is less than the crossover point, the scaling is applied + * to the view's transform and the graph nodes, labels, etc grow + * smaller. This preserves the overall shape of the graph. + * When the scale is larger than the crossover, the scaling is + * applied to the graph layout. The graph spreads out, but the + * vertices and labels grow no larger than their original size. + * + * @author Tom Nelson + */ +public class CrossoverScalingControl implements ScalingControl { + + /** + * Point where scale crosses over from view to layout. + */ + protected double crossover = 1.0; + + /** + * Sets the crossover point to the specified value. + * @param crossover the crossover point to use (defaults to 1.0) + */ + public void setCrossover(double crossover) { + this.crossover = crossover; + } + + /** + * @return the current crossover value + */ + public double getCrossover() { + return crossover; + } + + public void scale(VisualizationServer vv, float amount, Point2D at) { + + MutableTransformer layoutTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + MutableTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + double modelScale = layoutTransformer.getScale(); + double viewScale = viewTransformer.getScale(); + double inverseModelScale = Math.sqrt(crossover)/modelScale; + double inverseViewScale = Math.sqrt(crossover)/viewScale; + double scale = modelScale * viewScale; + + Point2D transformedAt = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, at); + + if((scale*amount - crossover)*(scale*amount - crossover) < 0.001) { + // close to the control point, return both Functions to a scale of sqrt crossover value + layoutTransformer.scale(inverseModelScale, inverseModelScale, transformedAt); + viewTransformer.scale(inverseViewScale, inverseViewScale, at); + } else if(scale*amount < crossover) { + // scale the viewTransformer, return the layoutTransformer to sqrt crossover value + viewTransformer.scale(amount, amount, at); + layoutTransformer.scale(inverseModelScale, inverseModelScale, transformedAt); + } else { + // scale the layoutTransformer, return the viewTransformer to crossover value + layoutTransformer.scale(amount, amount, transformedAt); + viewTransformer.scale(inverseViewScale, inverseViewScale, at); + } + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CubicCurveEdgeEffects.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CubicCurveEdgeEffects.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CubicCurveEdgeEffects.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/CubicCurveEdgeEffects.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,140 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.BasicVisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.util.ArrowFactory; + +public class CubicCurveEdgeEffects implements EdgeEffects { + + protected CubicCurve2D rawEdge = new CubicCurve2D.Float(); + protected Shape edgeShape; + protected Shape rawArrowShape; + protected Shape arrowShape; + protected VisualizationServer.Paintable edgePaintable; + protected VisualizationServer.Paintable arrowPaintable; + + + public CubicCurveEdgeEffects() { + this.rawEdge.setCurve(0.0f, 0.0f, 0.33f, 100, 0.66f, -50, 1.0f, 0.0f); + rawArrowShape = ArrowFactory.getNotchedArrow(20, 16, 8); + this.edgePaintable = new EdgePaintable(); + this.arrowPaintable = new ArrowPaintable(); + } + +// @Override + public void startEdgeEffects(BasicVisualizationServer vv, + Point2D down, Point2D out) { + transformEdgeShape(down, out); + vv.addPostRenderPaintable(edgePaintable); + } + +// @Override + public void midEdgeEffects(BasicVisualizationServer vv, + Point2D down, Point2D out) { + transformEdgeShape(down, out); + } + +// @Override + public void endEdgeEffects(BasicVisualizationServer vv) { + vv.removePostRenderPaintable(edgePaintable); + } + +// @Override + public void startArrowEffects(BasicVisualizationServer vv, + Point2D down, Point2D out) { + transformArrowShape(down, out); + vv.addPostRenderPaintable(arrowPaintable); + } + +// @Override + public void midArrowEffects(BasicVisualizationServer vv, + Point2D down, Point2D out) { + transformArrowShape(down, out); + } + +// @Override + public void endArrowEffects(BasicVisualizationServer vv) { + vv.removePostRenderPaintable(arrowPaintable); + } + + /** + * code lifted from PluggableRenderer to move an edge shape into an + * arbitrary position + */ + private void transformEdgeShape(Point2D down, Point2D out) { + float x1 = (float) down.getX(); + float y1 = (float) down.getY(); + float x2 = (float) out.getX(); + float y2 = (float) out.getY(); + + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + float dx = x2-x1; + float dy = y2-y1; + float thetaRadians = (float) Math.atan2(dy, dx); + xform.rotate(thetaRadians); + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist / rawEdge.getBounds().getWidth(), 1.0); + edgeShape = xform.createTransformedShape(rawEdge); + } + + private void transformArrowShape(Point2D down, Point2D out) { + float x1 = (float) down.getX(); + float y1 = (float) down.getY(); + float x2 = (float) out.getX(); + float y2 = (float) out.getY(); + + AffineTransform xform = AffineTransform.getTranslateInstance(x2, y2); + + float dx = x2-x1; + float dy = y2-y1; + float thetaRadians = (float) Math.atan2(dy, dx); + xform.rotate(thetaRadians); + arrowShape = xform.createTransformedShape(rawArrowShape); + } + /** + * Used for the edge creation visual effect during mouse drag + */ + class EdgePaintable implements VisualizationServer.Paintable { + + public void paint(Graphics g) { + if(edgeShape != null) { + Color oldColor = g.getColor(); + g.setColor(Color.black); + ((Graphics2D)g).draw(edgeShape); + g.setColor(oldColor); + } + } + + public boolean useTransform() { + return false; + } + } + + /** + * Used for the directed edge creation visual effect during mouse drag + */ + class ArrowPaintable implements VisualizationServer.Paintable { + + public void paint(Graphics g) { + if(arrowShape != null) { + Color oldColor = g.getColor(); + g.setColor(Color.black); + ((Graphics2D)g).fill(arrowShape); + g.setColor(oldColor); + } + } + + public boolean useTransform() { + return false; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/DefaultModalGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/DefaultModalGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/DefaultModalGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/DefaultModalGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.ItemSelectable; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + + +/** + * + * DefaultModalGraphMouse is a PluggableGraphMouse class that + * pre-installs a large collection of plugins for picking and + * transforming the graph. Additionally, it carries the notion + * of a Mode: Picking or Translating. Switching between modes + * allows for a more natural choice of mouse modifiers to + * be used for the various plugins. The default modifiers are + * intended to mimick those of mainstream software applications + * in order to be intuitive to users. + * + * To change between modes, two different controls are offered, + * a combo box and a menu system. These controls are lazily created + * in their respective 'getter' methods so they don't impact + * code that does not intend to use them. + * The menu control can be placed in an unused corner of the + * GraphZoomScrollPane, which is a common location for mouse + * mode selection menus in mainstream applications. + * + * @author Tom Nelson + */ +public class DefaultModalGraphMouse extends AbstractModalGraphMouse + implements ModalGraphMouse, ItemSelectable { + + /** + * create an instance with default values + * + */ + public DefaultModalGraphMouse() { + this(1.1f, 1/1.1f); + } + + /** + * create an instance with passed values + * @param in override value for scale in + * @param out override value for scale out + */ + public DefaultModalGraphMouse(float in, float out) { + super(in,out); + loadPlugins(); + setModeKeyListener(new ModeKeyAdapter(this)); + } + + /** + * create the plugins, and load the plugins for TRANSFORMING mode + * + */ + @Override + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out); + rotatingPlugin = new RotatingGraphMousePlugin(); + shearingPlugin = new ShearingGraphMousePlugin(); + + add(scalingPlugin); + setMode(Mode.TRANSFORMING); + } + + public static class ModeKeyAdapter extends KeyAdapter { + private char t = 't'; + private char p = 'p'; + protected ModalGraphMouse graphMouse; + + public ModeKeyAdapter(ModalGraphMouse graphMouse) { + this.graphMouse = graphMouse; + } + + public ModeKeyAdapter(char t, char p, ModalGraphMouse graphMouse) { + this.t = t; + this.p = p; + this.graphMouse = graphMouse; + } + + @Override + public void keyTyped(KeyEvent event) { + char keyChar = event.getKeyChar(); + if(keyChar == t) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + graphMouse.setMode(Mode.TRANSFORMING); + } else if(keyChar == p) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + graphMouse.setMode(Mode.PICKING); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeEffects.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeEffects.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeEffects.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeEffects.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,25 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.BasicVisualizationServer; + +public interface EdgeEffects { + + void startEdgeEffects(BasicVisualizationServer vv, + Point2D down, Point2D out); + + void midEdgeEffects(BasicVisualizationServer vv, + Point2D down, Point2D out); + + void endEdgeEffects(BasicVisualizationServer vv); + + void startArrowEffects(BasicVisualizationServer vv, + Point2D down, Point2D out); + + void midArrowEffects(BasicVisualizationServer vv, + Point2D down, Point2D out); + + void endArrowEffects(BasicVisualizationServer vv); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EdgeSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,25 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; + +/** + * interface to support the creation of new edges by the EditingGraphMousePlugin + * SimpleEdgeSupport is a sample implementation + * @author tanelso + * + * @param the vertex type + * @param the edge type + */ +public interface EdgeSupport { + + void startEdgeCreate(BasicVisualizationServer vv, V startVertex, + Point2D startPoint, EdgeType edgeType); + + void midEdgeCreate(BasicVisualizationServer vv, Point2D midPoint); + + void endEdgeCreate(BasicVisualizationServer vv, V endVertex); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,178 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import javax.swing.JComponent; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * A plugin that can create vertices, undirected edges, and directed edges + * using mouse gestures. + * + * vertexSupport and edgeSupport member classes are responsible for actually + * creating the new graph elements, and for repainting the view when changes + * were made. + * + * @author Tom Nelson + * + */ +public class EditingGraphMousePlugin extends AbstractGraphMousePlugin implements + MouseListener, MouseMotionListener { + + protected VertexSupport vertexSupport; + protected EdgeSupport edgeSupport; + private Creating createMode = Creating.UNDETERMINED; + private enum Creating { EDGE, VERTEX, UNDETERMINED } + + /** + * Creates an instance and prepares shapes for visual effects, using the default modifiers + * of BUTTON1_MASK. + * @param vertexFactory for creating vertices + * @param edgeFactory for creating edges + */ + public EditingGraphMousePlugin(Supplier vertexFactory, Supplier edgeFactory) { + this(MouseEvent.BUTTON1_MASK, vertexFactory, edgeFactory); + } + + /** + * Creates an instance and prepares shapes for visual effects. + * @param modifiers the mouse event modifiers to use + * @param vertexFactory for creating vertices + * @param edgeFactory for creating edges + */ + public EditingGraphMousePlugin(int modifiers, Supplier vertexFactory, Supplier edgeFactory) { + super(modifiers); + this.cursor = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); + this.vertexSupport = new SimpleVertexSupport(vertexFactory); + this.edgeSupport = new SimpleEdgeSupport(edgeFactory); + } + + /** + * Overridden to be more flexible, and pass events with + * key combinations. The default responds to both ButtonOne + * and ButtonOne+Shift + */ + @Override + public boolean checkModifiers(MouseEvent e) { + return (e.getModifiers() & modifiers) != 0; + } + + /** + * If the mouse is pressed in an empty area, create a new vertex there. + * If the mouse is pressed on an existing vertex, prepare to create + * an edge from that vertex to another + */ + @SuppressWarnings("unchecked") + public void mousePressed(MouseEvent e) { + if(checkModifiers(e)) { + final VisualizationViewer vv = + (VisualizationViewer)e.getSource(); + final Point2D p = e.getPoint(); + GraphElementAccessor pickSupport = vv.getPickSupport(); + if(pickSupport != null) { + final V vertex = pickSupport.getVertex(vv.getModel().getGraphLayout(), p.getX(), p.getY()); + if(vertex != null) { // get ready to make an edge + this.createMode = Creating.EDGE; + Graph graph = vv.getModel().getGraphLayout().getGraph(); + // set default edge type + EdgeType edgeType = (graph instanceof DirectedGraph) ? + EdgeType.DIRECTED : EdgeType.UNDIRECTED; + if((e.getModifiers() & MouseEvent.SHIFT_MASK) != 0 + && graph instanceof UndirectedGraph == false) { + edgeType = EdgeType.DIRECTED; + } + edgeSupport.startEdgeCreate(vv, vertex, e.getPoint(), edgeType); + } else { // make a new vertex + this.createMode = Creating.VERTEX; + vertexSupport.startVertexCreate(vv, e.getPoint()); + } + } + } + } + + /** + * If startVertex is non-null, and the mouse is released over an + * existing vertex, create an undirected edge from startVertex to + * the vertex under the mouse pointer. If shift was also pressed, + * create a directed edge instead. + */ + @SuppressWarnings("unchecked") + public void mouseReleased(MouseEvent e) { + if(checkModifiers(e)) { + final VisualizationViewer vv = + (VisualizationViewer)e.getSource(); + final Point2D p = e.getPoint(); + Layout layout = vv.getGraphLayout(); + if(createMode == Creating.EDGE) { + GraphElementAccessor pickSupport = vv.getPickSupport(); + V vertex = null; + if(pickSupport != null) { + vertex = pickSupport.getVertex(layout, p.getX(), p.getY()); + } + edgeSupport.endEdgeCreate(vv, vertex); + } else if(createMode == Creating.VERTEX){ + vertexSupport.endVertexCreate(vv, e.getPoint()); + } + } + createMode = Creating.UNDETERMINED; + } + + /** + * If startVertex is non-null, stretch an edge shape between + * startVertex and the mouse pointer to simulate edge creation + */ + @SuppressWarnings("unchecked") + public void mouseDragged(MouseEvent e) { + if(checkModifiers(e)) { + VisualizationViewer vv = + (VisualizationViewer)e.getSource(); + if(createMode == Creating.EDGE) { + edgeSupport.midEdgeCreate(vv, e.getPoint()); + } else if(createMode == Creating.VERTEX){ + vertexSupport.midVertexCreate(vv, e.getPoint()); + } + } + } + + public void mouseClicked(MouseEvent e) {} + public void mouseEntered(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(cursor); + } + public void mouseExited(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + public void mouseMoved(MouseEvent e) {} + + public VertexSupport getVertexSupport() { + return vertexSupport; + } + + public void setVertexSupport(VertexSupport vertexSupport) { + this.vertexSupport = vertexSupport; + } + + public EdgeSupport getEdgeSupport() { + return edgeSupport; + } + + public void setEdgeSupport(EdgeSupport edgeSupport) { + this.edgeSupport = edgeSupport; + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingModalGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingModalGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingModalGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingModalGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,312 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.ItemSelectable; +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JComboBox; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.plaf.basic.BasicIconFactory; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.visualization.MultiLayerTransformer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.annotations.AnnotatingGraphMousePlugin; + +public class EditingModalGraphMouse extends AbstractModalGraphMouse + implements ModalGraphMouse, ItemSelectable { + + protected Supplier vertexFactory; + protected Supplier edgeFactory; + protected EditingGraphMousePlugin editingPlugin; + protected LabelEditingGraphMousePlugin labelEditingPlugin; + protected EditingPopupGraphMousePlugin popupEditingPlugin; + protected AnnotatingGraphMousePlugin annotatingPlugin; + protected MultiLayerTransformer basicTransformer; + protected RenderContext rc; + + /** + * Creates an instance with the specified rendering context and vertex/edge factories, + * and with default zoom in/out values of 1.1 and 1/1.1. + * @param rc the rendering context + * @param vertexFactory used to construct vertices + * @param edgeFactory used to construct edges + */ + public EditingModalGraphMouse(RenderContext rc, + Supplier vertexFactory, Supplier edgeFactory) { + this(rc, vertexFactory, edgeFactory, 1.1f, 1/1.1f); + } + + /** + * Creates an instance with the specified rendering context and vertex/edge factories, + * and with the specified zoom in/out values. + * @param rc the rendering context + * @param vertexFactory used to construct vertices + * @param edgeFactory used to construct edges + * @param in amount to zoom in by for each action + * @param out amount to zoom out by for each action + */ + public EditingModalGraphMouse(RenderContext rc, + Supplier vertexFactory, Supplier edgeFactory, float in, float out) { + super(in,out); + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + this.rc = rc; + this.basicTransformer = rc.getMultiLayerTransformer(); + loadPlugins(); + setModeKeyListener(new ModeKeyAdapter(this)); + } + + /** + * create the plugins, and load the plugins for TRANSFORMING mode + * + */ + @Override + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + translatingPlugin = new TranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out); + rotatingPlugin = new RotatingGraphMousePlugin(); + shearingPlugin = new ShearingGraphMousePlugin(); + editingPlugin = new EditingGraphMousePlugin(vertexFactory, edgeFactory); + labelEditingPlugin = new LabelEditingGraphMousePlugin(); + annotatingPlugin = new AnnotatingGraphMousePlugin(rc); + popupEditingPlugin = new EditingPopupGraphMousePlugin(vertexFactory, edgeFactory); + add(scalingPlugin); + setMode(Mode.EDITING); + } + + /** + * setter for the Mode. + */ + @Override + public void setMode(Mode mode) { + if(this.mode != mode) { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + this.mode, ItemEvent.DESELECTED)); + this.mode = mode; + if(mode == Mode.TRANSFORMING) { + setTransformingMode(); + } else if(mode == Mode.PICKING) { + setPickingMode(); + } else if(mode == Mode.EDITING) { + setEditingMode(); + } else if(mode == Mode.ANNOTATING) { + setAnnotatingMode(); + } + if(modeBox != null) { + modeBox.setSelectedItem(mode); + } + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, mode, ItemEvent.SELECTED)); + } + } + + @Override + protected void setPickingMode() { + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + remove(editingPlugin); + remove(annotatingPlugin); + add(pickingPlugin); + add(animatedPickingPlugin); + add(labelEditingPlugin); + add(popupEditingPlugin); + } + + @Override + protected void setTransformingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(editingPlugin); + remove(annotatingPlugin); + add(translatingPlugin); + add(rotatingPlugin); + add(shearingPlugin); + add(labelEditingPlugin); + add(popupEditingPlugin); + } + + protected void setEditingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + remove(labelEditingPlugin); + remove(annotatingPlugin); + add(editingPlugin); + add(popupEditingPlugin); + } + + protected void setAnnotatingMode() { + remove(pickingPlugin); + remove(animatedPickingPlugin); + remove(translatingPlugin); + remove(rotatingPlugin); + remove(shearingPlugin); + remove(labelEditingPlugin); + remove(editingPlugin); + remove(popupEditingPlugin); + add(annotatingPlugin); + } + + + /** + * @return the modeBox. + */ + @Override + public JComboBox getModeComboBox() { + if(modeBox == null) { + modeBox = new JComboBox( + new Mode[]{Mode.TRANSFORMING, Mode.PICKING, Mode.EDITING, Mode.ANNOTATING}); + modeBox.addItemListener(getModeListener()); + } + modeBox.setSelectedItem(mode); + return modeBox; + } + + /** + * create (if necessary) and return a menu that will change + * the mode + * @return the menu + */ + @Override + public JMenu getModeMenu() { + if(modeMenu == null) { + modeMenu = new JMenu();// { + Icon icon = BasicIconFactory.getMenuArrowIcon(); + modeMenu.setIcon(BasicIconFactory.getMenuArrowIcon()); + modeMenu.setPreferredSize(new Dimension(icon.getIconWidth()+10, + icon.getIconHeight()+10)); + + final JRadioButtonMenuItem transformingButton = + new JRadioButtonMenuItem(Mode.TRANSFORMING.toString()); + transformingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.TRANSFORMING); + } + }}); + + final JRadioButtonMenuItem pickingButton = + new JRadioButtonMenuItem(Mode.PICKING.toString()); + pickingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.PICKING); + } + }}); + + final JRadioButtonMenuItem editingButton = + new JRadioButtonMenuItem(Mode.EDITING.toString()); + editingButton.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + setMode(Mode.EDITING); + } + }}); + + ButtonGroup radio = new ButtonGroup(); + radio.add(transformingButton); + radio.add(pickingButton); + radio.add(editingButton); + transformingButton.setSelected(true); + modeMenu.add(transformingButton); + modeMenu.add(pickingButton); + modeMenu.add(editingButton); + modeMenu.setToolTipText("Menu for setting Mouse Mode"); + addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if(e.getStateChange() == ItemEvent.SELECTED) { + if(e.getItem() == Mode.TRANSFORMING) { + transformingButton.setSelected(true); + } else if(e.getItem() == Mode.PICKING) { + pickingButton.setSelected(true); + } else if(e.getItem() == Mode.EDITING) { + editingButton.setSelected(true); + } + } + }}); + } + return modeMenu; + } + + public static class ModeKeyAdapter extends KeyAdapter { + private char t = 't'; + private char p = 'p'; + private char e = 'e'; + private char a = 'a'; + protected ModalGraphMouse graphMouse; + + public ModeKeyAdapter(ModalGraphMouse graphMouse) { + this.graphMouse = graphMouse; + } + + public ModeKeyAdapter(char t, char p, char e, char a, ModalGraphMouse graphMouse) { + this.t = t; + this.p = p; + this.e = e; + this.a = a; + this.graphMouse = graphMouse; + } + + @Override + public void keyTyped(KeyEvent event) { + char keyChar = event.getKeyChar(); + if(keyChar == t) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + graphMouse.setMode(Mode.TRANSFORMING); + } else if(keyChar == p) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + graphMouse.setMode(Mode.PICKING); + } else if(keyChar == e) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + graphMouse.setMode(Mode.EDITING); + } else if(keyChar == a) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); + graphMouse.setMode(Mode.ANNOTATING); + } + } + } + + /** + * @return the annotatingPlugin + */ + public AnnotatingGraphMousePlugin getAnnotatingPlugin() { + return annotatingPlugin; + } + + /** + * @return the editingPlugin + */ + public EditingGraphMousePlugin getEditingPlugin() { + return editingPlugin; + } + + /** + * @return the labelEditingPlugin + */ + public LabelEditingGraphMousePlugin getLabelEditingPlugin() { + return labelEditingPlugin; + } + + /** + * @return the popupEditingPlugin + */ + public EditingPopupGraphMousePlugin getPopupEditingPlugin() { + return popupEditingPlugin; + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingPopupGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingPopupGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingPopupGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/EditingPopupGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,115 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.util.Set; + +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JPopupMenu; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.DirectedGraph; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.UndirectedGraph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.picking.PickedState; + +/** + * a plugin that uses popup menus to create vertices, undirected edges, + * and directed edges. + * + * @author Tom Nelson + * + */ +public class EditingPopupGraphMousePlugin extends AbstractPopupGraphMousePlugin { + + protected Supplier vertexFactory; + protected Supplier edgeFactory; + + public EditingPopupGraphMousePlugin(Supplier vertexFactory, Supplier edgeFactory) { + this.vertexFactory = vertexFactory; + this.edgeFactory = edgeFactory; + } + + @SuppressWarnings({ "unchecked", "serial" }) + protected void handlePopup(MouseEvent e) { + final VisualizationViewer vv = + (VisualizationViewer)e.getSource(); + final Layout layout = vv.getGraphLayout(); + final Graph graph = layout.getGraph(); + final Point2D p = e.getPoint(); + GraphElementAccessor pickSupport = vv.getPickSupport(); + if(pickSupport != null) { + + final V vertex = pickSupport.getVertex(layout, p.getX(), p.getY()); + final E edge = pickSupport.getEdge(layout, p.getX(), p.getY()); + final PickedState pickedVertexState = vv.getPickedVertexState(); + final PickedState pickedEdgeState = vv.getPickedEdgeState(); + + JPopupMenu popup = new JPopupMenu(); + if(vertex != null) { + Set picked = pickedVertexState.getPicked(); + if(picked.size() > 0) { + if(graph instanceof UndirectedGraph == false) { + JMenu directedMenu = new JMenu("Create Directed Edge"); + popup.add(directedMenu); + for(final V other : picked) { + directedMenu.add(new AbstractAction("["+other+","+vertex+"]") { + public void actionPerformed(ActionEvent e) { + graph.addEdge(edgeFactory.get(), + other, vertex, EdgeType.DIRECTED); + vv.repaint(); + } + }); + } + } + if(graph instanceof DirectedGraph == false) { + JMenu undirectedMenu = new JMenu("Create Undirected Edge"); + popup.add(undirectedMenu); + for(final V other : picked) { + undirectedMenu.add(new AbstractAction("[" + other+","+vertex+"]") { + public void actionPerformed(ActionEvent e) { + graph.addEdge(edgeFactory.get(), + other, vertex); + vv.repaint(); + } + }); + } + } + } + popup.add(new AbstractAction("Delete Vertex") { + public void actionPerformed(ActionEvent e) { + pickedVertexState.pick(vertex, false); + graph.removeVertex(vertex); + vv.repaint(); + }}); + } else if(edge != null) { + popup.add(new AbstractAction("Delete Edge") { + public void actionPerformed(ActionEvent e) { + pickedEdgeState.pick(edge, false); + graph.removeEdge(edge); + vv.repaint(); + }}); + } else { + popup.add(new AbstractAction("Create Vertex") { + public void actionPerformed(ActionEvent e) { + V newVertex = vertexFactory.get(); + graph.addVertex(newVertex); + layout.setLocation(newVertex, vv.getRenderContext().getMultiLayerTransformer().inverseTransform(p)); + vv.repaint(); + } + }); + } + if(popup.getComponentCount() > 0) { + popup.show(vv, e.getX(), e.getY()); + } + } + } +} + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseAdapter.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseAdapter.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseAdapter.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseAdapter.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 6, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/** + * Simple extension of MouseAdapter that supplies modifier + * checking + * + * @author Tom Nelson + * + */ +public class GraphMouseAdapter extends MouseAdapter { + + protected int modifiers; + + public GraphMouseAdapter(int modifiers) { + this.modifiers = modifiers; + } + + public int getModifiers() { + return modifiers; + } + + public void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + protected boolean checkModifiers(MouseEvent e) { + return e.getModifiers() == modifiers; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseListener.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseListener.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseListener.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMouseListener.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Feb 17, 2004 + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; + +/** + * This interface allows users to register listeners to register to receive + * vertex clicks. + * + * @author danyelf + */ +public interface GraphMouseListener { + + void graphClicked(V v, MouseEvent me); + void graphPressed(V v, MouseEvent me); + void graphReleased(V v, MouseEvent me); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/GraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 6, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; + +/** + * the interface for all plugins to the PluggableGraphMouse + * @author Tom Nelson + * + */ +public interface GraphMousePlugin { + + /** + * @return the mouse event modifiers that will activate this plugin + */ + int getModifiers(); + + /** + * @param modifiers the mouse event modifiers that will activate this plugin + */ + void setModifiers(int modifiers); + + /** + * compare the set modifiers against those of the supplied event + * @param e an event to compare to + * @return whether the member modifiers match the event modifiers + */ + boolean checkModifiers(MouseEvent e); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LabelEditingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LabelEditingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LabelEditingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LabelEditingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.geom.Point2D; + +import javax.swing.JOptionPane; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.util.MapSettableTransformer; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * + * + * @author Tom Nelson + */ +public class LabelEditingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener { + + /** + * the picked Vertex, if any + */ + protected V vertex; + + /** + * the picked Edge, if any + */ + protected E edge; + + /** + * create an instance with default settings + */ + public LabelEditingGraphMousePlugin() { + this(InputEvent.BUTTON1_MASK); + } + + /** + * create an instance with overrides + * @param selectionModifiers for primary selection + */ + public LabelEditingGraphMousePlugin(int selectionModifiers) { + super(selectionModifiers); + this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + } + + /** + * For primary modifiers (default, MouseButton1): + * pick a single Vertex or Edge that + * is under the mouse pointer. If no Vertex or edge is under + * the pointer, unselect all picked Vertices and edges, and + * set up to draw a rectangle for multiple selection + * of contained Vertices. + * For additional selection (default Shift+MouseButton1): + * Add to the selection, a single Vertex or Edge that is + * under the mouse pointer. If a previously picked Vertex + * or Edge is under the pointer, it is un-picked. + * If no vertex or Edge is under the pointer, set up + * to draw a multiple selection rectangle (as above) + * but do not unpick previously picked elements. + * + * @param e the event + */ + @SuppressWarnings("unchecked") + public void mouseClicked(MouseEvent e) { + if (e.getModifiers() == modifiers && e.getClickCount() == 2) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + GraphElementAccessor pickSupport = vv.getPickSupport(); + if (pickSupport != null) { + Function vs = vv.getRenderContext().getVertexLabelTransformer(); + if (vs instanceof MapSettableTransformer) { + MapSettableTransformer mst = + (MapSettableTransformer)vs; + Layout layout = vv.getGraphLayout(); + // p is the screen point for the mouse event + Point2D p = e.getPoint(); + + V vertex = pickSupport.getVertex(layout, p.getX(), p.getY()); + if(vertex != null) { + String newLabel = vs.apply(vertex); + newLabel = JOptionPane.showInputDialog("New Vertex Label for "+vertex); + if(newLabel != null) { + mst.set(vertex, newLabel); + vv.repaint(); + } + return; + } + } + Function es = vv.getRenderContext().getEdgeLabelTransformer(); + if (es instanceof MapSettableTransformer) { + MapSettableTransformer mst = + (MapSettableTransformer)es; + Layout layout = vv.getGraphLayout(); + // p is the screen point for the mouse event + Point2D p = e.getPoint(); + // take away the view transform + Point2D ip = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, p); + E edge = pickSupport.getEdge(layout, ip.getX(), ip.getY()); + if(edge != null) { + String newLabel = JOptionPane.showInputDialog("New Edge Label for "+edge); + if(newLabel != null) { + mst.set(edge, newLabel); + vv.repaint(); + } + return; + } + } + } + e.consume(); + } + } + + /** + * If the mouse is dragging a rectangle, pick the + * Vertices contained in that rectangle + * + * clean up settings from mousePressed + */ + public void mouseReleased(MouseEvent e) { + } + + /** + * If the mouse is over a picked vertex, drag all picked + * vertices with the mouse. + * If the mouse is not over a Vertex, draw the rectangle + * to select multiple Vertices + * + */ + + public void mousePressed(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LayoutScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LayoutScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LayoutScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LayoutScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * LayoutScalingControl applies a scaling transformation to the graph layout. + * The Vertices get closer or farther apart, but do not themselves change + * size. ScalingGraphMouse uses MouseWheelEvents to apply the scaling. + * + * @author Tom Nelson + */ +public class LayoutScalingControl implements ScalingControl { + + /** + * zoom the display in or out, depending on the direction of the + * mouse wheel motion. + */ + public void scale(VisualizationServer vv, float amount, Point2D from) { + + Point2D ivtfrom = vv.getRenderContext().getMultiLayerTransformer() + .inverseTransform(Layer.VIEW, from); + MutableTransformer modelTransformer = vv.getRenderContext().getMultiLayerTransformer() + .getTransformer(Layer.LAYOUT); + modelTransformer.scale(amount, amount, ivtfrom); + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensMagnificationGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensMagnificationGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensMagnificationGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensMagnificationGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * HyperbolicMagnificationGraphMousePlugin changes the magnification + * within the Hyperbolic projection of the HyperbolicTransformer. + * + * @author Tom Nelson + */ +public class LensMagnificationGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseWheelListener { + + protected final float floor; + protected final float ceiling; + protected final float delta; + + /** + * Creates an instance with modifier of CTRL_MASK, and default min/max/delta zoom values + * of 1/4/0.2. + */ + public LensMagnificationGraphMousePlugin() { + this(MouseEvent.CTRL_MASK); + } + + /** + * Creates an instance with modifier of CTRL_MASK, and the specified zoom parameters. + * @param floor the minimum zoom value + * @param ceiling the maximum zoom value + * @param delta the change in zoom value caused by each mouse event + */ + public LensMagnificationGraphMousePlugin(float floor, float ceiling, float delta) { + this(MouseEvent.CTRL_MASK, floor, ceiling, delta); + } + + /** + * Creates an instance with the specified modifiers and the default min/max/delta zoom values + * of 1/4/0.2. + * @param modifiers the mouse event modifiers to specify + */ + public LensMagnificationGraphMousePlugin(int modifiers) { + this(modifiers, 1.0f, 4.0f, .2f); + } + + /** + * Creates an instance with the specified mouse event modifiers and zoom parameters. + * @param modifiers the mouse event modifiers to specify + * @param floor the minimum zoom value + * @param ceiling the maximum zoom value + * @param delta the change in zoom value caused by each mouse event + */ + public LensMagnificationGraphMousePlugin(int modifiers, float floor, float ceiling, float delta) { + super(modifiers); + this.floor = floor; + this.ceiling = ceiling; + this.delta = delta; + } + + /** + * override to check equality with a mask + */ + public boolean checkModifiers(MouseEvent e) { + return (e.getModifiers() & modifiers) != 0; + } + + private void changeMagnification(MutableTransformer transformer, float delta) { + if(transformer instanceof LensTransformer) { + LensTransformer ht = (LensTransformer)transformer; + float magnification = ht.getMagnification() + delta; + magnification = Math.max(floor, magnification); + magnification = Math.min(magnification, ceiling); + ht.setMagnification(magnification); + } + } + /** + * zoom the display in or out, depending on the direction of the + * mouse wheel motion. + */ + public void mouseWheelMoved(MouseWheelEvent e) { + boolean accepted = checkModifiers(e); + float delta = this.delta; + if(accepted == true) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + MutableTransformer modelTransformer = vv.getRenderContext().getMultiLayerTransformer() + .getTransformer(Layer.LAYOUT); + MutableTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer() + .getTransformer(Layer.VIEW); + int amount = e.getWheelRotation(); + if(amount < 0) { + delta = -delta; + } + changeMagnification(modelTransformer, delta); + changeMagnification(viewTransformer, delta); + vv.repaint(); + e.consume(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensTranslatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensTranslatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensTranslatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/LensTranslatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Extends TranslatingGraphMousePlugin and adds the capability + * to drag and resize the viewing + * lens in the graph view. Mouse1 in the center moves the lens, + * mouse1 on the edge resizes the lens. The default mouse button and + * modifiers can be overridden in the constructor. + * + * + * @author Tom Nelson + */ +public class LensTranslatingGraphMousePlugin extends TranslatingGraphMousePlugin +implements MouseListener, MouseMotionListener { + + protected boolean dragOnLens; + protected boolean dragOnEdge; + protected double edgeOffset; + /** + * create an instance with default modifiers + */ + public LensTranslatingGraphMousePlugin() { + this(MouseEvent.BUTTON1_MASK); + } + + /** + * create an instance with passed modifer value + * @param modifiers the mouse event modifier to activate this function + */ + public LensTranslatingGraphMousePlugin(int modifiers) { + super(modifiers); + } + + /** + * Check the event modifiers. Set the 'down' point for later + * use. If this event satisfies the modifiers, change the cursor + * to the system 'move cursor' + * @param e the event + */ + public void mousePressed(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + MutableTransformer vt = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof LensTransformer) { + vt = ((LensTransformer)vt).getDelegate(); + } + Point2D p = vt.inverseTransform(e.getPoint()); + boolean accepted = checkModifiers(e); + if(accepted) { + vv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + testViewCenter(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT), p); + testViewCenter(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW), p); + vv.repaint(); + } + super.mousePressed(e); + } + + /** + * called to change the location of the lens + * @param Function + * @param point + */ + private void setViewCenter(MutableTransformer transformer, Point2D point) { + if(transformer instanceof LensTransformer) { + LensTransformer ht = + (LensTransformer)transformer; + ht.setViewCenter(point); + } + } + + /** + * called to change the radius of the lens + * @param Function + * @param point + */ + private void setViewRadius(MutableTransformer transformer, Point2D point) { + if(transformer instanceof LensTransformer) { + LensTransformer ht = + (LensTransformer)transformer; + double distanceFromCenter = ht.getDistanceFromCenter(point); + ht.setViewRadius(distanceFromCenter+edgeOffset); + } + } + + /** + * called to set up translating the lens center or changing the size + * @param Function + * @param point + */ + private void testViewCenter(MutableTransformer transformer, Point2D point) { + if(transformer instanceof LensTransformer) { + LensTransformer ht = + (LensTransformer)transformer; + double distanceFromCenter = ht.getDistanceFromCenter(point); + if(distanceFromCenter < 10) { + ht.setViewCenter(point); + dragOnLens = true; + } else if(Math.abs(distanceFromCenter - ht.getViewRadius()) < 10) { + edgeOffset = ht.getViewRadius() - distanceFromCenter; + ht.setViewRadius(distanceFromCenter+edgeOffset); + dragOnEdge = true; + } + } + } + + /** + * unset the 'down' point and change the cursoe back to the system + * default cursor + */ + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + dragOnLens = false; + dragOnEdge = false; + edgeOffset = 0; + } + + /** + * check the modifiers. If accepted, move or resize the lens according + * to the dragging of the mouse pointer + * @param e the event + */ + public void mouseDragged(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + MutableTransformer vt = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof LensTransformer) { + vt = ((LensTransformer)vt).getDelegate(); + } + Point2D p = vt.inverseTransform(e.getPoint()); + boolean accepted = checkModifiers(e); + + if(accepted ) { + MutableTransformer modelTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + vv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + if(dragOnLens) { + setViewCenter(modelTransformer, p); + setViewCenter(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW), p); + e.consume(); + vv.repaint(); + + } else if(dragOnEdge) { + + setViewRadius(modelTransformer, p); + setViewRadius(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW), p); + e.consume(); + vv.repaint(); + + } else { + + MutableTransformer mt = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + Point2D iq = vt.inverseTransform(down); + iq = mt.inverseTransform(iq); + Point2D ip = vt.inverseTransform(e.getPoint()); + ip = mt.inverseTransform(ip); + float dx = (float) (ip.getX()-iq.getX()); + float dy = (float) (ip.getY()-iq.getY()); + + modelTransformer.translate(dx, dy); + down.x = e.getX(); + down.y = e.getY(); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 26, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.ItemListener; + +import edu.uci.ics.jung.visualization.VisualizationViewer.GraphMouse; + +/** + * Interface for a GraphMouse that supports modality. + * + * @author Tom Nelson + * + */ +public interface ModalGraphMouse extends GraphMouse { + + void setMode(Mode mode); + + /** + * @return Returns the modeListener. + */ + ItemListener getModeListener(); + + /** + */ + enum Mode { TRANSFORMING, PICKING, ANNOTATING, EDITING } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalLensGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalLensGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalLensGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalLensGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 26, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.Component; +import java.awt.Cursor; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * an implementation of the AbstractModalGraphMouse that includes plugins for + * manipulating a view that is using a LensTransformer. + * + * @author Tom Nelson + * + */ +public class ModalLensGraphMouse extends AbstractModalGraphMouse implements + ModalGraphMouse { + + /** + * not included in the base class + */ + protected LensMagnificationGraphMousePlugin magnificationPlugin; + + public ModalLensGraphMouse() { + this(1.1f, 1/1.1f); + } + + public ModalLensGraphMouse(float in, float out) { + this(in, out, new LensMagnificationGraphMousePlugin()); + } + + public ModalLensGraphMouse(LensMagnificationGraphMousePlugin magnificationPlugin) { + this(1.1f, 1/1.1f, magnificationPlugin); + } + + public ModalLensGraphMouse(float in, float out, LensMagnificationGraphMousePlugin magnificationPlugin) { + super(in,out); + this.in = in; + this.out = out; + this.magnificationPlugin = magnificationPlugin; + loadPlugins(); + setModeKeyListener(new ModeKeyAdapter(this)); + } + + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new AnimatedPickingGraphMousePlugin(); + translatingPlugin = new LensTranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, in, out); + rotatingPlugin = new RotatingGraphMousePlugin(); + shearingPlugin = new ShearingGraphMousePlugin(); + + add(magnificationPlugin); + add(scalingPlugin); + + setMode(Mode.TRANSFORMING); + } + public static class ModeKeyAdapter extends KeyAdapter { + private char t = 't'; + private char p = 'p'; + protected ModalGraphMouse graphMouse; + + public ModeKeyAdapter(ModalGraphMouse graphMouse) { + this.graphMouse = graphMouse; + } + + public ModeKeyAdapter(char t, char p, ModalGraphMouse graphMouse) { + this.t = t; + this.p = p; + this.graphMouse = graphMouse; + } + + public void keyTyped(KeyEvent event) { + char keyChar = event.getKeyChar(); + if(keyChar == t) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + graphMouse.setMode(Mode.TRANSFORMING); + } else if(keyChar == p) { + ((Component)event.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + graphMouse.setMode(Mode.PICKING); + } + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalSatelliteGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalSatelliteGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalSatelliteGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ModalSatelliteGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 26, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.InputEvent; +/** + * + * @author Tom Nelson + * + */ +@SuppressWarnings("rawtypes") +public class ModalSatelliteGraphMouse extends DefaultModalGraphMouse implements + ModalGraphMouse { + + public ModalSatelliteGraphMouse() { + this(1.1f, 1/1.1f); + } + + public ModalSatelliteGraphMouse(float in, float out) { + super(in, out); + } + + protected void loadPlugins() { + pickingPlugin = new PickingGraphMousePlugin(); + animatedPickingPlugin = new SatelliteAnimatedPickingGraphMousePlugin(); + translatingPlugin = new SatelliteTranslatingGraphMousePlugin(InputEvent.BUTTON1_MASK); + scalingPlugin = new SatelliteScalingGraphMousePlugin(new CrossoverScalingControl(), 0); + rotatingPlugin = new SatelliteRotatingGraphMousePlugin(); + shearingPlugin = new SatelliteShearingGraphMousePlugin(); + + add(scalingPlugin); + + setMode(Mode.TRANSFORMING); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/MouseListenerTranslator.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/MouseListenerTranslator.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/MouseListenerTranslator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/MouseListenerTranslator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Feb 17, 2004 + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * This class translates mouse clicks into vertex clicks + * + * @author danyelf + */ +public class MouseListenerTranslator extends MouseAdapter { + + private VisualizationViewer vv; + private GraphMouseListener gel; + + /** + * @param gel listens for mouse events + * @param vv the viewer used for visualization + */ + public MouseListenerTranslator(GraphMouseListener gel, VisualizationViewer vv) { + this.gel = gel; + this.vv = vv; + } + + /** + * Transform the point to the coordinate system in the + * VisualizationViewer, then use either PickSuuport + * (if available) or Layout to find a Vertex + * @param point + * @return + */ + private V getVertex(Point2D point) { + // adjust for scale and offset in the VisualizationViewer + Point2D p = point; + //vv.getRenderContext().getBasicTransformer().inverseViewTransform(point); + GraphElementAccessor pickSupport = vv.getPickSupport(); + Layout layout = vv.getGraphLayout(); + V v = null; + if(pickSupport != null) { + v = pickSupport.getVertex(layout, p.getX(), p.getY()); + } + return v; + } + /** + * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) + */ + public void mouseClicked(MouseEvent e) { + V v = getVertex(e.getPoint()); + if ( v != null ) { + gel.graphClicked(v, e ); + } + } + + /** + * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) + */ + public void mousePressed(MouseEvent e) { + V v = getVertex(e.getPoint()); + if ( v != null ) { + gel.graphPressed(v, e ); + } + } + + /** + * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) + */ + public void mouseReleased(MouseEvent e) { + V v = getVertex(e.getPoint()); + if ( v != null ) { + gel.graphReleased(v, e ); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + + + +

        Mechanisms for manipulating and controlling a graph visualization, largely +in terms of mouse plugins. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PickingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PickingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PickingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PickingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.picking.PickedState; + +/** + * PickingGraphMousePlugin supports the picking of graph elements + * with the mouse. MouseButtonOne picks a single vertex + * or edge, and MouseButtonTwo adds to the set of selected Vertices + * or EdgeType. If a Vertex is selected and the mouse is dragged while + * on the selected Vertex, then that Vertex will be repositioned to + * follow the mouse until the button is released. + * + * @author Tom Nelson + */ +public class PickingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + * the picked Vertex, if any + */ + protected V vertex; + + /** + * the picked Edge, if any + */ + protected E edge; + + /** + * the x distance from the picked vertex center to the mouse point + */ + protected double offsetx; + + /** + * the y distance from the picked vertex center to the mouse point + */ + protected double offsety; + + /** + * controls whether the Vertices may be moved with the mouse + */ + protected boolean locked; + + /** + * additional modifiers for the action of adding to an existing + * selection + */ + protected int addToSelectionModifiers; + + /** + * used to draw a rectangle to contain picked vertices + */ + protected Rectangle2D rect = new Rectangle2D.Float(); + + /** + * the Paintable for the lens picking rectangle + */ + protected Paintable lensPaintable; + + /** + * color for the picking rectangle + */ + protected Color lensColor = Color.cyan; + + /** + * create an instance with default settings + */ + public PickingGraphMousePlugin() { + this(InputEvent.BUTTON1_MASK, InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK); + } + + /** + * create an instance with overides + * @param selectionModifiers for primary selection + * @param addToSelectionModifiers for additional selection + */ + public PickingGraphMousePlugin(int selectionModifiers, int addToSelectionModifiers) { + super(selectionModifiers); + this.addToSelectionModifiers = addToSelectionModifiers; + this.lensPaintable = new LensPaintable(); + this.cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + } + + /** + * @return Returns the lensColor. + */ + public Color getLensColor() { + return lensColor; + } + + /** + * @param lensColor The lensColor to set. + */ + public void setLensColor(Color lensColor) { + this.lensColor = lensColor; + } + + /** + * a Paintable to draw the rectangle used to pick multiple + * Vertices + * @author Tom Nelson + * + */ + class LensPaintable implements Paintable { + + public void paint(Graphics g) { + Color oldColor = g.getColor(); + g.setColor(lensColor); + ((Graphics2D)g).draw(rect); + g.setColor(oldColor); + } + + public boolean useTransform() { + return false; + } + } + + /** + * For primary modifiers (default, MouseButton1): + * pick a single Vertex or Edge that + * is under the mouse pointer. If no Vertex or edge is under + * the pointer, unselect all picked Vertices and edges, and + * set up to draw a rectangle for multiple selection + * of contained Vertices. + * For additional selection (default Shift+MouseButton1): + * Add to the selection, a single Vertex or Edge that is + * under the mouse pointer. If a previously picked Vertex + * or Edge is under the pointer, it is un-picked. + * If no vertex or Edge is under the pointer, set up + * to draw a multiple selection rectangle (as above) + * but do not unpick previously picked elements. + * + * @param e the event + */ + @SuppressWarnings("unchecked") + public void mousePressed(MouseEvent e) { + down = e.getPoint(); + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + GraphElementAccessor pickSupport = vv.getPickSupport(); + PickedState pickedVertexState = vv.getPickedVertexState(); + PickedState pickedEdgeState = vv.getPickedEdgeState(); + if(pickSupport != null && pickedVertexState != null) { + Layout layout = vv.getGraphLayout(); + if(e.getModifiers() == modifiers) { + rect.setFrameFromDiagonal(down,down); + // p is the screen point for the mouse event + Point2D ip = e.getPoint(); + + vertex = pickSupport.getVertex(layout, ip.getX(), ip.getY()); + if(vertex != null) { + if(pickedVertexState.isPicked(vertex) == false) { + pickedVertexState.clear(); + pickedVertexState.pick(vertex, true); + } + // layout.getLocation applies the layout Function so + // q is transformed by the layout Function only + Point2D q = layout.apply(vertex); + // transform the mouse point to graph coordinate system + Point2D gp = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.LAYOUT, ip); + + offsetx = (float) (gp.getX()-q.getX()); + offsety = (float) (gp.getY()-q.getY()); + } else if((edge = pickSupport.getEdge(layout, ip.getX(), ip.getY())) != null) { + pickedEdgeState.clear(); + pickedEdgeState.pick(edge, true); + } else { + vv.addPostRenderPaintable(lensPaintable); + pickedEdgeState.clear(); + pickedVertexState.clear(); + } + + } else if(e.getModifiers() == addToSelectionModifiers) { + vv.addPostRenderPaintable(lensPaintable); + rect.setFrameFromDiagonal(down,down); + Point2D ip = e.getPoint(); + vertex = pickSupport.getVertex(layout, ip.getX(), ip.getY()); + if(vertex != null) { + boolean wasThere = pickedVertexState.pick(vertex, !pickedVertexState.isPicked(vertex)); + if(wasThere) { + vertex = null; + } else { + + // layout.getLocation applies the layout Function so + // q is transformed by the layout Function only + Point2D q = layout.apply(vertex); + // translate mouse point to graph coord system + Point2D gp = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.LAYOUT, ip); + + offsetx = (float) (gp.getX()-q.getX()); + offsety = (float) (gp.getY()-q.getY()); + } + } else if((edge = pickSupport.getEdge(layout, ip.getX(), ip.getY())) != null) { + pickedEdgeState.pick(edge, !pickedEdgeState.isPicked(edge)); + } + } + } + if(vertex != null) e.consume(); + } + + /** + * If the mouse is dragging a rectangle, pick the + * Vertices contained in that rectangle + * + * clean up settings from mousePressed + */ + @SuppressWarnings("unchecked") + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + if(e.getModifiers() == modifiers) { + if(down != null) { + Point2D out = e.getPoint(); + + if(vertex == null && heyThatsTooClose(down, out, 5) == false) { + pickContainedVertices(vv, down, out, true); + } + } + } else if(e.getModifiers() == this.addToSelectionModifiers) { + if(down != null) { + Point2D out = e.getPoint(); + + if(vertex == null && heyThatsTooClose(down,out,5) == false) { + pickContainedVertices(vv, down, out, false); + } + } + } + down = null; + vertex = null; + edge = null; + rect.setFrame(0,0,0,0); + vv.removePostRenderPaintable(lensPaintable); + vv.repaint(); + } + + /** + * If the mouse is over a picked vertex, drag all picked + * vertices with the mouse. + * If the mouse is not over a Vertex, draw the rectangle + * to select multiple Vertices + * + */ + @SuppressWarnings("unchecked") + public void mouseDragged(MouseEvent e) { + if(locked == false) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + if(vertex != null) { + Point p = e.getPoint(); + Point2D graphPoint = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(p); + Point2D graphDown = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down); + Layout layout = vv.getGraphLayout(); + double dx = graphPoint.getX()-graphDown.getX(); + double dy = graphPoint.getY()-graphDown.getY(); + PickedState ps = vv.getPickedVertexState(); + + for(V v : ps.getPicked()) { + Point2D vp = layout.apply(v); + vp.setLocation(vp.getX()+dx, vp.getY()+dy); + layout.setLocation(v, vp); + } + down = p; + + } else { + Point2D out = e.getPoint(); + if(e.getModifiers() == this.addToSelectionModifiers || + e.getModifiers() == modifiers) { + rect.setFrameFromDiagonal(down,out); + } + } + if(vertex != null) e.consume(); + vv.repaint(); + } + } + + /** + * rejects picking if the rectangle is too small, like + * if the user meant to select one vertex but moved the + * mouse slightly + * @param p + * @param q + * @param min + * @return + */ + private boolean heyThatsTooClose(Point2D p, Point2D q, double min) { + return Math.abs(p.getX()-q.getX()) < min && + Math.abs(p.getY()-q.getY()) < min; + } + + /** + * pick the vertices inside the rectangle created from points 'down' and 'out' (two diagonally + * opposed corners of the rectangle) + * + * @param vv the viewer containing the layout and picked state + * @param down one corner of the rectangle + * @param out the other corner of the rectangle + * @param clear whether to reset existing picked state + */ + protected void pickContainedVertices(VisualizationViewer vv, Point2D down, Point2D out, boolean clear) { + + Layout layout = vv.getGraphLayout(); + PickedState pickedVertexState = vv.getPickedVertexState(); + + Rectangle2D pickRectangle = new Rectangle2D.Double(); + pickRectangle.setFrameFromDiagonal(down,out); + + if(pickedVertexState != null) { + if(clear) { + pickedVertexState.clear(); + } + GraphElementAccessor pickSupport = vv.getPickSupport(); + + Collection picked = pickSupport.getVertices(layout, pickRectangle); + for(V v : picked) { + pickedVertexState.pick(v, true); + } + } + } + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(cursor); + } + + public void mouseExited(MouseEvent e) { + JComponent c = (JComponent)e.getSource(); + c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + public void mouseMoved(MouseEvent e) { + } + + /** + * @return Returns the locked. + */ + public boolean isLocked() { + return locked; + } + + /** + * @param locked The locked to set. + */ + public void setLocked(boolean locked) { + this.locked = locked; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PluggableGraphMouse.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PluggableGraphMouse.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PluggableGraphMouse.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/PluggableGraphMouse.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 7, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.util.LinkedHashSet; +import java.util.Set; + +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * a GraphMouse that accepts plugins for various mouse events. + * + * @author Tom Nelson + * + * + */ +public class PluggableGraphMouse implements VisualizationViewer.GraphMouse { + + MouseListener[] mouseListeners; + MouseMotionListener[] mouseMotionListeners; + MouseWheelListener[] mouseWheelListeners; + Set mousePluginList = new LinkedHashSet(); + Set mouseMotionPluginList = new LinkedHashSet(); + Set mouseWheelPluginList = new LinkedHashSet(); + + public void add(GraphMousePlugin plugin) { + if(plugin instanceof MouseListener) { + mousePluginList.add(plugin); + mouseListeners = null; + } + if(plugin instanceof MouseMotionListener) { + mouseMotionPluginList.add((MouseMotionListener)plugin); + mouseMotionListeners = null; + } + if(plugin instanceof MouseWheelListener) { + mouseWheelPluginList.add((MouseWheelListener)plugin); + mouseWheelListeners = null; + } + } + + public void remove(GraphMousePlugin plugin) { + if(plugin instanceof MouseListener) { + boolean wasThere = mousePluginList.remove(plugin); + if(wasThere) mouseListeners = null; + } + if(plugin instanceof MouseMotionListener) { + boolean wasThere = mouseMotionPluginList.remove(plugin); + if(wasThere) mouseMotionListeners = null; + } + if(plugin instanceof MouseWheelListener) { + boolean wasThere = mouseWheelPluginList.remove(plugin); + if(wasThere) mouseWheelListeners = null; + } + } + + private void checkMouseListeners() { + if(mouseListeners == null) { + mouseListeners = (MouseListener[]) + mousePluginList.toArray(new MouseListener[mousePluginList.size()]); + } + } + + private void checkMouseMotionListeners() { + if(mouseMotionListeners == null){ + mouseMotionListeners = (MouseMotionListener[]) + mouseMotionPluginList.toArray(new MouseMotionListener[mouseMotionPluginList.size()]); + } + } + + private void checkMouseWheelListeners() { + if(mouseWheelListeners == null) { + mouseWheelListeners = (MouseWheelListener[]) + mouseWheelPluginList.toArray(new MouseWheelListener[mouseWheelPluginList.size()]); + } + } + + public void mouseClicked(MouseEvent e) { + checkMouseListeners(); + for(int i=0; i vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + down = e.getPoint(); + if(accepted) { + vv.setCursor(cursor); + } + } + + /** + * unset the down point and change the cursor back to the default + */ + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + down = null; + vv.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + /** + * check the modifiers. If accepted, use the mouse drag motion + * to rotate the graph + */ + public void mouseDragged(MouseEvent e) { + if(down == null) return; + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + MutableTransformer modelTransformer = + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + // rotate + vv.setCursor(cursor); + + Point2D center = vv.getCenter(); + Point2D q = down; + Point2D p = e.getPoint(); + Point2D v1 = new Point2D.Double(center.getX()-p.getX(), center.getY()-p.getY()); + Point2D v2 = new Point2D.Double(center.getX()-q.getX(), center.getY()-q.getY()); + double theta = angleBetween(v1, v2); + modelTransformer.rotate(theta, vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, center)); + down.x = e.getX(); + down.y = e.getY(); + + e.consume(); + } + } + + /** + * Returns the angle between two vectors from the origin + * to points v1 and v2. + * @param v1 the first point + * @param v2 the second point + * @return the angle between two vectors from the origin through points v1 and v2 + */ + protected double angleBetween(Point2D v1, Point2D v2) { + double x1 = v1.getX(); + double y1 = v1.getY(); + double x2 = v2.getX(); + double y2 = v2.getY(); + // cross product for direction + double cross = x1*y2 - x2*y1; + int cw = 1; + if(cross > 0) { + cw = -1; + } + // dot product for angle + double angle = + cw*Math.acos( ( x1*x2 + y1*y2 ) / + ( Math.sqrt( x1*x1 + y1*y1 ) * + Math.sqrt( x2*x2 + y2*y2 ) ) ); + if(Double.isNaN(angle)) { + angle = 0; + } + return angle; + } + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseMoved(MouseEvent e) { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteAnimatedPickingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteAnimatedPickingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteAnimatedPickingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteAnimatedPickingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * A version of the AnimatedPickingGraphMousePlugin that is for + * the SatelliteVisualizationViewer. The difference it that when + * you pick a Vertex in the Satellite View, the 'master view' is + * translated to move that Vertex to the center. + * @see AnimatedPickingGraphMousePlugin + * @author Tom Nelson + */ +public class SatelliteAnimatedPickingGraphMousePlugin extends AnimatedPickingGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + * create an instance + * + */ + public SatelliteAnimatedPickingGraphMousePlugin() { + this(InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK); + } + + public SatelliteAnimatedPickingGraphMousePlugin(int selectionModifiers) { + super(selectionModifiers); + } + + /** + * override subclass method to translate the master view instead + * of this satellite view + * + */ + @SuppressWarnings("unchecked") + public void mouseReleased(MouseEvent e) { + if (e.getModifiers() == modifiers) { + final VisualizationViewer vv = (VisualizationViewer) e.getSource(); + if (vv instanceof SatelliteVisualizationViewer) { + final VisualizationViewer vvMaster = + ((SatelliteVisualizationViewer) vv).getMaster(); + + if (vertex != null) { + Layout layout = vvMaster.getGraphLayout(); + Point2D q = layout.apply(vertex); + Point2D lvc = + vvMaster.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.LAYOUT, vvMaster.getCenter()); + final double dx = (lvc.getX() - q.getX()) / 10; + final double dy = (lvc.getY() - q.getY()) / 10; + + Runnable animator = new Runnable() { + + public void run() { + for (int i = 0; i < 10; i++) { + vvMaster.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).translate(dx, + dy); + try { + Thread.sleep(100); + } catch (InterruptedException ex) { + } + } + } + }; + Thread thread = new Thread(animator); + thread.start(); + } + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteRotatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteRotatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteRotatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteRotatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 15, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Mouse events in the SatelliteView that match the modifiers + * will cause the Main view to rotate + * @see RotatingGraphMousePlugin + * @author Tom Nelson + * + */ +public class SatelliteRotatingGraphMousePlugin extends RotatingGraphMousePlugin { + + public SatelliteRotatingGraphMousePlugin() { + super(); + } + + public SatelliteRotatingGraphMousePlugin(int modifiers) { + super(modifiers); + } + /** + * check the modifiers. If accepted, use the mouse drag motion + * to rotate the graph in the master view + */ + public void mouseDragged(MouseEvent e) { + if(down == null) return; + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + if(vv instanceof SatelliteVisualizationViewer) { + VisualizationViewer vvMaster = + ((SatelliteVisualizationViewer)vv).getMaster(); + + MutableTransformer modelTransformerMaster = + vvMaster.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + + // rotate + vv.setCursor(cursor); + // I want to compute rotation based on the view coordinates of the + // lens center in the satellite view. + // translate the master view center to layout coords, then translate + // that point to the satellite view's view coordinate system.... + Point2D center = vv.getRenderContext().getMultiLayerTransformer().transform(vvMaster.getRenderContext().getMultiLayerTransformer().inverseTransform(vvMaster.getCenter())); + Point2D q = down; + Point2D p = e.getPoint(); + Point2D v1 = new Point2D.Double(center.getX()-p.getX(), center.getY()-p.getY()); + Point2D v2 = new Point2D.Double(center.getX()-q.getX(), center.getY()-q.getY()); + double theta = angleBetween(v1, v2); + modelTransformerMaster.rotate(-theta, + vvMaster.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, vvMaster.getCenter())); + down.x = e.getX(); + down.y = e.getY(); + } + e.consume(); + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteScalingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteScalingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteScalingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteScalingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 15, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseWheelEvent; + +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * Overrides ScalingGraphMousePlugin so that mouse events in the + * satellite view will cause scaling in the main view + * + * @see ScalingGraphMousePlugin + * @author Tom Nelson + * + */ +public class SatelliteScalingGraphMousePlugin extends ScalingGraphMousePlugin { + + public SatelliteScalingGraphMousePlugin(ScalingControl scaler, int modifiers) { + super(scaler, modifiers); + } + + public SatelliteScalingGraphMousePlugin(ScalingControl scaler, int modifiers, float in, float out) { + super(scaler, modifiers, in, out); + } + + /** + * zoom the master view display in or out, depending on the direction of the + * mouse wheel motion. + */ + public void mouseWheelMoved(MouseWheelEvent e) { + boolean accepted = checkModifiers(e); + if(accepted == true) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + + if(vv instanceof SatelliteVisualizationViewer) { + VisualizationViewer vvMaster = + ((SatelliteVisualizationViewer)vv).getMaster(); + + int amount = e.getWheelRotation(); + + if(amount > 0) { + scaler.scale(vvMaster, in, vvMaster.getCenter()); + + } else if(amount < 0) { + scaler.scale(vvMaster, out, vvMaster.getCenter()); + } + e.consume(); + vv.repaint(); + } + } + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteShearingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteShearingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteShearingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteShearingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 15, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Overrides ShearingGraphMousePlugin so that mouse events in the + * satellite view cause shearing of the main view + * + * @see ShearingGraphMousePlugin + * @author Tom Nelson + * + */ +public class SatelliteShearingGraphMousePlugin extends ShearingGraphMousePlugin { + + public SatelliteShearingGraphMousePlugin() { + super(); + } + + public SatelliteShearingGraphMousePlugin(int modifiers) { + super(modifiers); + } + + /** + * overridden to shear the main view + */ + public void mouseDragged(MouseEvent e) { + if(down == null) return; + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + if(vv instanceof SatelliteVisualizationViewer) { + VisualizationViewer vvMaster = + ((SatelliteVisualizationViewer)vv).getMaster(); + + MutableTransformer modelTransformerMaster = + vvMaster.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + + vv.setCursor(cursor); + Point2D q = down; + Point2D p = e.getPoint(); + float dx = (float) (p.getX()-q.getX()); + float dy = (float) (p.getY()-q.getY()); + + Dimension d = vv.getSize(); + float shx = 2.f*dx/d.height; + float shy = 2.f*dy/d.width; + // I want to compute shear based on the view coordinates of the + // lens center in the satellite view. + // translate the master view center to layout coords, then translate + // that point to the satellite view's view coordinate system.... + Point2D center = vv.getRenderContext().getMultiLayerTransformer().transform(vvMaster.getRenderContext().getMultiLayerTransformer().inverseTransform(vvMaster.getCenter())); + if(p.getX() < center.getX()) { + shy = -shy; + } + if(p.getY() < center.getY()) { + shx = -shx; + } + modelTransformerMaster.shear(-shx, -shy, vvMaster.getCenter()); + + down.x = e.getX(); + down.y = e.getY(); + } + e.consume(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteTranslatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteTranslatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteTranslatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteTranslatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 15, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * Overrides TranslatingGraphMousePlugin so that mouse events in + * the satellite view cause translating of the main view + * + * @see TranslatingGraphMousePlugin + * @author Tom Nelson + * + */ +public class SatelliteTranslatingGraphMousePlugin extends + TranslatingGraphMousePlugin { + + public SatelliteTranslatingGraphMousePlugin() { + super(); + } + + public SatelliteTranslatingGraphMousePlugin(int modifiers) { + super(modifiers); + } + + /** + * Check the modifiers. If accepted, translate the main view according + * to the dragging of the mouse pointer in the satellite view + * @param e the event + */ + public void mouseDragged(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + if(vv instanceof SatelliteVisualizationViewer) { + VisualizationViewer vvMaster = + ((SatelliteVisualizationViewer)vv).getMaster(); + + MutableTransformer modelTransformerMaster = + vvMaster.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + vv.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + try { + Point2D q = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down); + Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(e.getPoint()); + float dx = (float) (p.getX()-q.getX()); + float dy = (float) (p.getY()-q.getY()); + + modelTransformerMaster.translate(-dx, -dy); + down.x = e.getX(); + down.y = e.getY(); + } catch(RuntimeException ex) { + System.err.println("down = "+down+", e = "+e); + throw ex; + } + } + e.consume(); + } + } + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteVisualizationViewer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteVisualizationViewer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteVisualizationViewer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SatelliteVisualizationViewer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 15, 2005 + */ + +package edu.uci.ics.jung.visualization.control; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableAffineTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; + +/** + * A VisualizationViewer that can act as a satellite view for another + * (master) VisualizationViewer. In this view, the full graph is always visible + * and all mouse actions affect the graph in the master view. + * + * A rectangular shape in the satellite view shows the visible bounds of + * the master view. + * + * @author Tom Nelson + * + * + */ +@SuppressWarnings("serial") +public class SatelliteVisualizationViewer + extends VisualizationViewer { + + /** + * the master VisualizationViewer that this is a satellite view for + */ + protected VisualizationViewer master; + + /** + * @param master the master VisualizationViewer for which this is a satellite view + * @param preferredSize the specified size of the component + */ + public SatelliteVisualizationViewer(VisualizationViewer master, + Dimension preferredSize) { + super(master.getModel(), preferredSize); + this.master = master; + + // create a graph mouse with custom plugins to affect the master view + ModalGraphMouse gm = new ModalSatelliteGraphMouse(); + setGraphMouse(gm); + + // this adds the Lens to the satellite view + addPreRenderPaintable(new ViewLens(this, master)); + + // get a copy of the current layout transform + // it may have been scaled to fit the graph + AffineTransform modelLayoutTransform = + new AffineTransform(master.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getTransform()); + + // I want no layout transformations in the satellite view + // this resets the auto-scaling that occurs in the super constructor + getRenderContext().getMultiLayerTransformer().setTransformer(Layer.LAYOUT, new MutableAffineTransformer(modelLayoutTransform)); + + // make sure the satellite listens for changes in the master + master.addChangeListener(this); + + // share the picked state of the master + setPickedVertexState(master.getPickedVertexState()); + setPickedEdgeState(master.getPickedEdgeState()); + } + + /** + * @return Returns the master. + */ + public VisualizationViewer getMaster() { + return master; + } + + /** + * A four-sided shape that represents the visible part of the + * master view and is drawn in the satellite view + * + * @author Tom Nelson + * + * + */ + static class ViewLens implements Paintable { + + VisualizationViewer master; + VisualizationViewer vv; + + public ViewLens(VisualizationViewer vv, VisualizationViewer master) { + this.vv = vv; + this.master = master; + } + public void paint(Graphics g) { + ShapeTransformer masterViewTransformer = + master.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + ShapeTransformer masterLayoutTransformer = master.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + ShapeTransformer vvLayoutTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + + Shape lens = master.getBounds(); + lens = masterViewTransformer.inverseTransform(lens); + lens = masterLayoutTransformer.inverseTransform(lens); + lens = vvLayoutTransformer.transform(lens); + Graphics2D g2d = (Graphics2D)g; + Color old = g.getColor(); + Color lensColor = master.getBackground(); + vv.setBackground(lensColor.darker()); + g.setColor(lensColor); + g2d.fill(lens); + g.setColor(Color.gray); + g2d.draw(lens); + g.setColor(old); + } + + public boolean useTransform() { + return true; + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.VisualizationServer; + +public interface ScalingControl { + + /** + * zoom the display in or out + * @param vv the VisualizationViewer + * @param amount how much to adjust scale by + * @param at where to adjust scale from + */ + void scale(VisualizationServer vv, float amount, Point2D at); + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ScalingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.VisualizationViewer; + +/** + * ScalingGraphMouse applies a scaling transformation to the graph layout. + * The Vertices get closer or farther apart, but do not themselves change + * size. ScalingGraphMouse uses MouseWheelEvents to apply the scaling. + * + * @author Tom Nelson + */ +public class ScalingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseWheelListener { + + /** + * the amount to zoom in by + */ + protected float in = 1.1f; + /** + * the amount to zoom out by + */ + protected float out = 1/1.1f; + + /** + * whether to center the zoom at the current mouse position + */ + protected boolean zoomAtMouse = true; + + /** + * controls scaling operations + */ + protected ScalingControl scaler; + + public ScalingGraphMousePlugin(ScalingControl scaler, int modifiers) { + this(scaler, modifiers, 1.1f, 1/1.1f); + } + + public ScalingGraphMousePlugin(ScalingControl scaler, int modifiers, float in, float out) { + super(modifiers); + this.scaler = scaler; + this.in = in; + this.out = out; + } + /** + * @param zoomAtMouse The zoomAtMouse to set. + */ + public void setZoomAtMouse(boolean zoomAtMouse) { + this.zoomAtMouse = zoomAtMouse; + } + + public boolean checkModifiers(MouseEvent e) { + return e.getModifiers() == modifiers || (e.getModifiers() & modifiers) != 0; + } + + /** + * zoom the display in or out, depending on the direction of the + * mouse wheel motion. + */ + public void mouseWheelMoved(MouseWheelEvent e) { + boolean accepted = checkModifiers(e); + if(accepted == true) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + Point2D mouse = e.getPoint(); + Point2D center = vv.getCenter(); + int amount = e.getWheelRotation(); + if(zoomAtMouse) { + if(amount > 0) { + scaler.scale(vv, in, mouse); + } else if(amount < 0) { + scaler.scale(vv, out, mouse); + } + } else { + if(amount > 0) { + scaler.scale(vv, in, center); + } else if(amount < 0) { + scaler.scale(vv, out, center); + } + } + e.consume(); + vv.repaint(); + } + } + /** + * @return Returns the zoom in value. + */ + public float getIn() { + return in; + } + /** + * @param in The zoom in value to set. + */ + public void setIn(float in) { + this.in = in; + } + /** + * @return Returns the zoom out value. + */ + public float getOut() { + return out; + } + /** + * @param out The zoom out value to set. + */ + public void setOut(float out) { + this.out = out; + } + + public ScalingControl getScaler() { + return scaler; + } + + public void setScaler(ScalingControl scaler) { + this.scaler = scaler; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ShearingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ShearingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ShearingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ShearingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.Toolkit; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.util.Collections; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * ShearingGraphMousePlugin allows the user to drag with the mouse + * to shear the transform either in the horizontal or vertical direction. + * By default, the control or meta key must be depressed to activate + * shearing. + * + * + * @author Tom Nelson + */ +public class ShearingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + private static int mask = MouseEvent.CTRL_MASK; + + static { + if(System.getProperty("os.name").startsWith("Mac")) { + mask = MouseEvent.META_MASK; + } + } + /** + * create an instance with default modifier values + */ + public ShearingGraphMousePlugin() { + this(MouseEvent.BUTTON1_MASK | mask); + } + + /** + * create an instance with passed modifier values + * @param modifiers the mouse modifiers to use + */ + public ShearingGraphMousePlugin(int modifiers) { + super(modifiers); + Dimension cd = Toolkit.getDefaultToolkit().getBestCursorSize(16,16); + BufferedImage cursorImage = + new BufferedImage(cd.width,cd.height,BufferedImage.TYPE_INT_ARGB); + Graphics g = cursorImage.createGraphics(); + Graphics2D g2 = (Graphics2D)g; + g2.addRenderingHints(Collections.singletonMap(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + g.setColor(new Color(0,0,0,0)); + g.fillRect(0,0,16,16); + + int left = 0; + int top = 0; + int right = 15; + int bottom = 15; + + g.setColor(Color.white); + g2.setStroke(new BasicStroke(3)); + g.drawLine(left+2,top+5,right-2,top+5); + g.drawLine(left+2,bottom-5,right-2,bottom-5); + g.drawLine(left+2,top+5,left+4,top+3); + g.drawLine(left+2,top+5,left+4,top+7); + g.drawLine(right-2,bottom-5,right-4,bottom-3); + g.drawLine(right-2,bottom-5,right-4,bottom-7); + + g.setColor(Color.black); + g2.setStroke(new BasicStroke(1)); + g.drawLine(left+2,top+5,right-2,top+5); + g.drawLine(left+2,bottom-5,right-2,bottom-5); + g.drawLine(left+2,top+5,left+4,top+3); + g.drawLine(left+2,top+5,left+4,top+7); + g.drawLine(right-2,bottom-5,right-4,bottom-3); + g.drawLine(right-2,bottom-5,right-4,bottom-7); + g.dispose(); + cursor = Toolkit.getDefaultToolkit().createCustomCursor(cursorImage, new Point(), "RotateCursor"); + } + + public void mousePressed(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + down = e.getPoint(); + if(accepted) { + vv.setCursor(cursor); + } + } + + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + down = null; + vv.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + public void mouseDragged(MouseEvent e) { + if(down == null) return; + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + MutableTransformer modelTransformer = + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + vv.setCursor(cursor); + Point2D q = down; + Point2D p = e.getPoint(); + float dx = (float) (p.getX()-q.getX()); + float dy = (float) (p.getY()-q.getY()); + + Dimension d = vv.getSize(); + float shx = 2.f*dx/d.height; + float shy = 2.f*dy/d.width; + Point2D center = vv.getCenter(); + if(p.getX() < center.getX()) { + shy = -shy; + } + if(p.getY() < center.getY()) { + shx = -shx; + } + modelTransformer.shear(shx, shy, center); + down.x = e.getX(); + down.y = e.getY(); + + e.consume(); + } + } + + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleEdgeSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleEdgeSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleEdgeSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleEdgeSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,86 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; + +public class SimpleEdgeSupport implements EdgeSupport { + + protected Point2D down; + protected EdgeEffects edgeEffects; + protected EdgeType edgeType; + protected Supplier edgeFactory; + protected V startVertex; + + public SimpleEdgeSupport(Supplier edgeFactory) { + this.edgeFactory = edgeFactory; + this.edgeEffects = new CubicCurveEdgeEffects(); + } + +// @Override + public void startEdgeCreate(BasicVisualizationServer vv, + V startVertex, Point2D startPoint, EdgeType edgeType) { + this.startVertex = startVertex; + this.down = startPoint; + this.edgeType = edgeType; + this.edgeEffects.startEdgeEffects(vv, startPoint, startPoint); + if(edgeType == EdgeType.DIRECTED) { + this.edgeEffects.startArrowEffects(vv, startPoint, startPoint); + } + vv.repaint(); + } + +// @Override + public void midEdgeCreate(BasicVisualizationServer vv, + Point2D midPoint) { + if(startVertex != null) { + this.edgeEffects.midEdgeEffects(vv, down, midPoint); + if(this.edgeType == EdgeType.DIRECTED) { + this.edgeEffects.midArrowEffects(vv, down, midPoint); + } + vv.repaint(); + } + } + +// @Override + public void endEdgeCreate(BasicVisualizationServer vv, V endVertex) { + if(startVertex != null) { + Graph graph = vv.getGraphLayout().getGraph(); + graph.addEdge(edgeFactory.get(), startVertex, endVertex, edgeType); + vv.repaint(); + } + startVertex = null; + edgeType = EdgeType.UNDIRECTED; + edgeEffects.endEdgeEffects(vv); + edgeEffects.endArrowEffects(vv); + } + + public EdgeEffects getEdgeEffects() { + return edgeEffects; + } + + public void setEdgeEffects(EdgeEffects edgeEffects) { + this.edgeEffects = edgeEffects; + } + + public EdgeType getEdgeType() { + return edgeType; + } + + public void setEdgeType(EdgeType edgeType) { + this.edgeType = edgeType; + } + + public Supplier getEdgeFactory() { + return edgeFactory; + } + + public void setEdgeFactory(Supplier edgeFactory) { + this.edgeFactory = edgeFactory; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleVertexSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleVertexSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleVertexSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/SimpleVertexSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,56 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import com.google.common.base.Supplier; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; + +/** + * sample implementation showing how to use the VertexSupport interface member of the + * EditingGraphMousePlugin. + * override midVertexCreate and endVertexCreate for more elaborate implementations + * @author tanelso + * + * @param the vertex type + * @param the edge type + */ +public class SimpleVertexSupport implements VertexSupport { + + protected Supplier vertexFactory; + + public SimpleVertexSupport(Supplier vertexFactory) { + this.vertexFactory = vertexFactory; + } + + public void startVertexCreate(BasicVisualizationServer vv, + Point2D point) { + V newVertex = vertexFactory.get(); + Layout layout = vv.getGraphLayout(); + Graph graph = layout.getGraph(); + graph.addVertex(newVertex); + layout.setLocation(newVertex, vv.getRenderContext().getMultiLayerTransformer().inverseTransform(point)); + vv.repaint(); + } + + public void midVertexCreate(BasicVisualizationServer vv, + Point2D point) { + // noop + } + + public void endVertexCreate(BasicVisualizationServer vv, + Point2D point) { + //noop + } + + public Supplier getVertexFactory() { + return vertexFactory; + } + + public void setVertexFactory(Supplier vertexFactory) { + this.vertexFactory = vertexFactory; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/TranslatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/TranslatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/TranslatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/TranslatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * TranslatingGraphMousePlugin uses a MouseButtonOne press and + * drag gesture to translate the graph display in the x and y + * direction. The default MouseButtonOne modifier can be overridden + * to cause a different mouse gesture to translate the display. + * + * + * @author Tom Nelson + */ +public class TranslatingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + */ + public TranslatingGraphMousePlugin() { + this(MouseEvent.BUTTON1_MASK); + } + + /** + * create an instance with passed modifer value + * @param modifiers the mouse event modifier to activate this function + */ + public TranslatingGraphMousePlugin(int modifiers) { + super(modifiers); + this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); + } + + /** + * Check the event modifiers. Set the 'down' point for later + * use. If this event satisfies the modifiers, change the cursor + * to the system 'move cursor' + * @param e the event + */ + public void mousePressed(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + down = e.getPoint(); + if(accepted) { + vv.setCursor(cursor); + } + } + + /** + * unset the 'down' point and change the cursoe back to the system + * default cursor + */ + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + down = null; + vv.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + /** + * chack the modifiers. If accepted, translate the graph according + * to the dragging of the mouse pointer + * @param e the event + */ + public void mouseDragged(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + MutableTransformer modelTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + vv.setCursor(cursor); + try { + Point2D q = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(down); + Point2D p = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(e.getPoint()); + float dx = (float) (p.getX()-q.getX()); + float dy = (float) (p.getY()-q.getY()); + + modelTransformer.translate(dx, dy); + down.x = e.getX(); + down.y = e.getY(); + } catch(RuntimeException ex) { + System.err.println("down = "+down+", e = "+e); + throw ex; + } + + e.consume(); + vv.repaint(); + } + } + + public void mouseClicked(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseEntered(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseExited(MouseEvent e) { + // TODO Auto-generated method stub + + } + + public void mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/VertexSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/VertexSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/VertexSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/VertexSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,22 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.BasicVisualizationServer; + +/** + * interface to support the creation of new vertices by the EditingGraphMousePlugin. + * SimpleVertexSupport is a sample implementation. + * @author tanelso + * + * @param the vertex type + */ +public interface VertexSupport { + + void startVertexCreate(BasicVisualizationServer vv, Point2D point); + + void midVertexCreate(BasicVisualizationServer vv, Point2D point); + + void endVertexCreate(BasicVisualizationServer vv, Point2D point); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * ViewScalingGraphMouse applies a scaling transform to the View + * of the graph. This causes all elements of the graph to grow + * larger or smaller. ViewScalingGraphMouse, by default, is activated + * by the MouseWheel when the control key is pressed. The control + * key modifier can be overridden in the contstructor. + * + * @author Tom Nelson + */ +public class ViewScalingControl implements ScalingControl { + + /** + * zoom the display in or out, depending on the direction of the + * mouse wheel motion. + */ + public void scale(VisualizationServer vv, float amount, Point2D from) { + MutableTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + viewTransformer.scale(amount, amount, from); + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewTranslatingGraphMousePlugin.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewTranslatingGraphMousePlugin.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewTranslatingGraphMousePlugin.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/control/ViewTranslatingGraphMousePlugin.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 8, 2005 + * + */ +package edu.uci.ics.jung.visualization.control; + +import java.awt.Cursor; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * ViewTranslatingGraphMousePlugin uses a MouseButtonOne press and + * drag gesture to translate the graph display in the x and y + * direction by changing the AffineTransform applied to the Graphics2D. + * The default MouseButtonOne modifier can be overridden + * to cause a different mouse gesture to translate the display. + * + * + * @author Tom Nelson + */ +public class ViewTranslatingGraphMousePlugin extends AbstractGraphMousePlugin + implements MouseListener, MouseMotionListener { + + /** + */ + public ViewTranslatingGraphMousePlugin() { + this(MouseEvent.BUTTON1_MASK); + } + + /** + * create an instance with passed modifer value + * @param modifiers the mouse event modifier to activate this function + */ + public ViewTranslatingGraphMousePlugin(int modifiers) { + super(modifiers); + this.cursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); + } + + /** + * Check the event modifiers. Set the 'down' point for later + * use. If this event satisfies the modifiers, change the cursor + * to the system 'move cursor' + * @param e the event + */ + public void mousePressed(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + down = e.getPoint(); + if(accepted) { + vv.setCursor(cursor); + } + } + + /** + * unset the 'down' point and change the cursoe back to the system + * default cursor + */ + public void mouseReleased(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + down = null; + vv.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + + /** + * chack the modifiers. If accepted, translate the graph according + * to the dragging of the mouse pointer + * @param e the event + */ + public void mouseDragged(MouseEvent e) { + VisualizationViewer vv = (VisualizationViewer)e.getSource(); + boolean accepted = checkModifiers(e); + if(accepted) { + MutableTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + vv.setCursor(cursor); + try { + Point2D q = viewTransformer.inverseTransform(down); + Point2D p = viewTransformer.inverseTransform(e.getPoint()); + float dx = (float) (p.getX()-q.getX()); + float dy = (float) (p.getY()-q.getY()); + + viewTransformer.translate(dx, dy); + down.x = e.getX(); + down.y = e.getY(); + } catch(RuntimeException ex) { + System.err.println("down = "+down+", e = "+e); + throw ex; + } + + e.consume(); + } + } + + public void mouseClicked(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseMoved(MouseEvent e) { + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/AbstractVertexShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/AbstractVertexShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/AbstractVertexShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/AbstractVertexShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * Created on Jul 16, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +import edu.uci.ics.jung.visualization.util.VertexShapeFactory; + + + +/** + * + * @author Joshua O'Madadhain + */ +public abstract class AbstractVertexShapeTransformer implements SettableVertexShapeTransformer +{ + protected Function vsf; + protected Function varf; + protected VertexShapeFactory factory; + public final static int DEFAULT_SIZE = 8; + public final static float DEFAULT_ASPECT_RATIO = 1.0f; + + public AbstractVertexShapeTransformer(Function vsf, Function varf) + { + this.vsf = vsf; + this.varf = varf; + factory = new VertexShapeFactory(vsf, varf); + } + + public AbstractVertexShapeTransformer() + { + this(Functions.constant(DEFAULT_SIZE), + Functions.constant(DEFAULT_ASPECT_RATIO)); + } + + public void setSizeTransformer(Function vsf) + { + this.vsf = vsf; + factory = new VertexShapeFactory(vsf, varf); + } + + public void setAspectRatioTransformer(Function varf) + { + this.varf = varf; + factory = new VertexShapeFactory(vsf, varf); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ConstantDirectionalEdgeValueTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ConstantDirectionalEdgeValueTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ConstantDirectionalEdgeValueTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ConstantDirectionalEdgeValueTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Created on Oct 21, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; + + +/** + * Returns the constructor-specified value for each edge type. + * + * @author Joshua O'Madadhain + */ +public class ConstantDirectionalEdgeValueTransformer implements Function,E>,Number> +{ + protected Double undirected_value; + protected Double directed_value; + + /** + * + * @param undirected the value to return if the edge is undirected + * @param directed the value to return if the edge is directed + */ + public ConstantDirectionalEdgeValueTransformer(double undirected, double directed) + { + this.undirected_value = new Double(undirected); + this.directed_value = new Double(directed); + } + + public Number apply(Context,E> context) { + Graph graph = context.graph; + E e = context.element; + if (graph.getEdgeType(e) == EdgeType.DIRECTED) + return directed_value; + else + return undirected_value; + } + + /** + * Sets the value returned for undirected edges to value. + * @param value the new value to return for undirected edges + */ + public void setUndirectedValue(double value) + { + this.undirected_value = value; + } + + /** + * Sets the value returned for directed edges to value. + * @param value the new value to return for directed edges + */ + public void setDirectedValue(double value) + { + this.directed_value = value; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/DirectionalEdgeArrowTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/DirectionalEdgeArrowTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/DirectionalEdgeArrowTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/DirectionalEdgeArrowTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Created on Jul 18, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Shape; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.util.ArrowFactory; + +/** + * Returns wedge arrows for undirected edges and notched arrows + * for directed edges, of the specified dimensions. + * + * @author Joshua O'Madadhain + */ +public class DirectionalEdgeArrowTransformer implements Function,E>,Shape> { + protected Shape undirected_arrow; + protected Shape directed_arrow; + + public DirectionalEdgeArrowTransformer(int length, int width, int notch_depth) + { + directed_arrow = ArrowFactory.getNotchedArrow(width, length, notch_depth); + undirected_arrow = ArrowFactory.getWedgeArrow(width, length); + } + + /** + * + */ + public Shape apply(Context,E> context) + { + if (context.graph.getEdgeType(context.element) == EdgeType.DIRECTED) + return directed_arrow; + else + return undirected_arrow; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EdgeShape.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EdgeShape.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EdgeShape.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EdgeShape.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on March 10, 2005 + */ +package edu.uci.ics.jung.visualization.decorators; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.QuadCurve2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.util.ArrowFactory; + + +/** + * An interface for decorators that return a + * Shape for a specified edge. + * + * All edge shapes must be defined so that their endpoints are at + * (0,0) and (1,0). They will be scaled, rotated and translated into + * position by the PluggableRenderer. + * + * @author Tom Nelson + * @param the vertex type + * @param the edge type + */ +public class EdgeShape { + private static final Line2D LINE = new Line2D.Float(0.0f, 0.0f, 1.0f, 0.0f); + private static final GeneralPath BENT_LINE = new GeneralPath(); + private static final QuadCurve2D QUAD_CURVE = new QuadCurve2D.Float(); + private static final CubicCurve2D CUBIC_CURVE = new CubicCurve2D.Float(); + private static final Ellipse2D ELLIPSE = new Ellipse2D.Float(-.5f, -.5f, 1, 1); + private static Rectangle2D BOX = new Rectangle2D.Float(); + + private static GeneralPath triangle; + private static GeneralPath bowtie; + + protected final Graph graph; + + /** + * A convenience instance for other edge shapes to use for self-loop edges + * where parallel instances will not overlay each other. + */ + protected final Loop loop; + + /** + * A convenience instance for other edge shapes to use for self-loop edges + * where parallel instances overlay each other. + */ + protected final SimpleLoop simpleLoop; + + protected final Box box; + + public EdgeShape(Graph g) { + this.graph = g; + this.box = new Box(); + this.loop = new Loop(); + this.simpleLoop = new SimpleLoop(); + } + + private Shape getLoopOrNull(E e) { + return getLoopOrNull(e, loop); + } + + private Shape getLoopOrNull(E e, Function loop) { + Pair endpoints = graph.getEndpoints(e); + checkNotNull(endpoints); + boolean isLoop = endpoints.getFirst().equals(endpoints.getSecond()); + if (isLoop) { + return loop.apply(e); + } + return null; + } + + public static EdgeShape.Line line(Graph graph) { + return new EdgeShape(graph).new Line(); + } + + public static EdgeShape.QuadCurve quadCurve(Graph graph) { + return new EdgeShape(graph).new QuadCurve(); + } + + public static EdgeShape.QuadCurve cubicCurve(Graph graph) { + return new EdgeShape(graph).new QuadCurve(); + } + + public static EdgeShape.Orthogonal orthogonal(Graph graph) { + return new EdgeShape(graph).new Orthogonal(); + } + + public static EdgeShape.Wedge wedge(Graph graph, int width) { + return new EdgeShape(graph).new Wedge(width); + } + + /** + * An edge shape that renders as a straight line between + * the vertex endpoints. + */ + public class Line implements Function { + /** + * Get the shape for this edge, returning either the + * shared instance or, in the case of self-loop edges, the + * Loop shared instance. + */ + public Shape apply(E e) { + Shape loop = getLoopOrNull(e); + return loop == null + ? LINE + : loop; + } + } + + private int getIndex(E e, EdgeIndexFunction edgeIndexFunction) { + return edgeIndexFunction == null + ? 1 + : edgeIndexFunction.getIndex(graph, e); + } + + /** + * An edge shape that renders as a bent-line between the + * vertex endpoints. + */ + public class BentLine extends ParallelEdgeShapeTransformer { + public void setEdgeIndexFunction(EdgeIndexFunction edgeIndexFunction) { + this.edgeIndexFunction = edgeIndexFunction; + loop.setEdgeIndexFunction(edgeIndexFunction); + } + + /** + * Get the shape for this edge, returning either the + * shared instance or, in the case of self-loop edges, the + * Loop shared instance. + */ + public Shape apply(E e) { + Shape edgeShape = getLoopOrNull(e); + if (edgeShape != null) { + return edgeShape; + } + + int index = getIndex(e, edgeIndexFunction); + float controlY = control_offset_increment + control_offset_increment * index; + BENT_LINE.reset(); + BENT_LINE.moveTo(0.0f, 0.0f); + BENT_LINE.lineTo(0.5f, controlY); + BENT_LINE.lineTo(1.0f, 1.0f); + return BENT_LINE; + } + + } + + /** + * An edge shape that renders as a QuadCurve between vertex + * endpoints. + */ + public class QuadCurve extends ParallelEdgeShapeTransformer { + @Override + public void setEdgeIndexFunction(EdgeIndexFunction parallelEdgeIndexFunction) { + this.edgeIndexFunction = parallelEdgeIndexFunction; + loop.setEdgeIndexFunction(parallelEdgeIndexFunction); + } + + /** + * Get the shape for this edge, returning either the + * shared instance or, in the case of self-loop edges, the + * Loop shared instance. + */ + public Shape apply(E e) { + Shape edgeShape = getLoopOrNull(e); + if (edgeShape != null) { + return edgeShape; + } + + int index = getIndex(e, edgeIndexFunction); + + float controlY = control_offset_increment + + control_offset_increment * index; + QUAD_CURVE.setCurve(0.0f, 0.0f, 0.5f, controlY, 1.0f, 0.0f); + return QUAD_CURVE; + } + } + + /** + * An edge shape that renders as a CubicCurve between vertex + * endpoints. The two control points are at + * (1/3*length, 2*controlY) and (2/3*length, controlY) + * giving a 'spiral' effect. + */ + public class CubicCurve extends ParallelEdgeShapeTransformer { + public void setEdgeIndexFunction(EdgeIndexFunction edgeIndexFunction) { + this.edgeIndexFunction = edgeIndexFunction; + loop.setEdgeIndexFunction(edgeIndexFunction); + } + + /** + * Get the shape for this edge, returning either the + * shared instance or, in the case of self-loop edges, the + * Loop shared instance. + */ + public Shape apply(E e) { + Shape edgeShape = getLoopOrNull(e); + if (edgeShape != null) { + return edgeShape; + } + + int index = getIndex(e, edgeIndexFunction); + + float controlY = control_offset_increment + + control_offset_increment * index; + CUBIC_CURVE.setCurve(0.0f, 0.0f, 0.33f, 2 * controlY, .66f, -controlY, + 1.0f, 0.0f); + return CUBIC_CURVE; + } + } + + /** + * An edge shape that renders as a loop with its nadir at the center of the + * vertex. Parallel instances will overlap. + * + * @author Tom Nelson + */ + public class SimpleLoop extends ParallelEdgeShapeTransformer { + public Shape apply(E e) { + return ELLIPSE; + } + } + + private Shape buildFrame(RectangularShape shape, int index) { + float x = -.5f; + float y = -.5f; + float diam = 1.f; + diam += diam * index/2; + x += x * index/2; + y += y * index/2; + + shape.setFrame(x, y, diam, diam); + + return shape; + } + + /** + * An edge shape that renders as a loop with its nadir at the + * center of the vertex. Parallel instances will not overlap. + */ + public class Loop extends ParallelEdgeShapeTransformer { + public Shape apply(E e) { + return buildFrame(ELLIPSE, getIndex(e, edgeIndexFunction)); + } + } + + /** + * An edge shape that renders as an isosceles triangle whose + * apex is at the destination vertex for directed edges, + * and as a "bowtie" shape for undirected edges. + * @author Joshua O'Madadhain + */ + public class Wedge extends ParallelEdgeShapeTransformer { + public Wedge(int width) { + triangle = ArrowFactory.getWedgeArrow(width, 1); + triangle.transform(AffineTransform.getTranslateInstance(1,0)); + bowtie = new GeneralPath(GeneralPath.WIND_EVEN_ODD); + bowtie.moveTo(0, width/2); + bowtie.lineTo(1, -width/2); + bowtie.lineTo(1, width/2); + bowtie.lineTo(0, -width/2); + bowtie.closePath(); + } + + public Shape apply(E e) { + Shape edgeShape = getLoopOrNull(e); + if (edgeShape != null) { + return edgeShape; + } + return (graph.getEdgeType(e) == EdgeType.DIRECTED) + ? triangle + : bowtie; + } + } + + /** + * An edge shape that renders as a diamond with its nadir at the + * center of the vertex. Parallel instances will not overlap. + */ + public class Box extends ParallelEdgeShapeTransformer { + public Shape apply(E e) { + return buildFrame(BOX, getIndex(e, edgeIndexFunction)); + } + } + + + /** + * An edge shape that renders as a bent-line between the vertex endpoints. + */ + public class Orthogonal extends ParallelEdgeShapeTransformer { + public Shape apply(E e) { + Shape loop = getLoopOrNull(e, box); + return loop == null + ? LINE + : loop; + } + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EllipseVertexShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EllipseVertexShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EllipseVertexShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/EllipseVertexShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * Created on Jul 16, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Shape; + +import com.google.common.base.Function; + +/** + * + * @author Joshua O'Madadhain + */ +public class EllipseVertexShapeTransformer extends AbstractVertexShapeTransformer + implements Function +{ + public EllipseVertexShapeTransformer() + { + } + public EllipseVertexShapeTransformer(Function vsf, Function varf) + { + super(vsf, varf); + } + + public Shape apply(V v) + { + return factory.getEllipse(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/GradientEdgePaintTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/GradientEdgePaintTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/GradientEdgePaintTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/GradientEdgePaintTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Created on Apr 8, 2005 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Paint; +import java.awt.geom.Point2D; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.util.SelfLoopEdgePredicate; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; + +/** + * Creates GradientPaint instances which can be used + * to paint an Edge. For DirectedEdges, + * the color will blend from c1 (source) to + * c2 (destination); for UndirectedEdges, + * the color will be c1 at each end and c2 + * in the middle. + * + * @author Joshua O'Madadhain + */ +public class GradientEdgePaintTransformer + implements Function +{ + protected Color c1; + protected Color c2; + protected VisualizationViewer vv; + protected BidirectionalTransformer transformer; + protected Predicate,E>> selfLoop = new SelfLoopEdgePredicate(); + + public GradientEdgePaintTransformer(Color c1, Color c2, + VisualizationViewer vv) + { + this.c1 = c1; + this.c2 = c2; + this.vv = vv; + this.transformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + } + + public Paint apply(E e) + { + Layout layout = vv.getGraphLayout(); + Pair p = layout.getGraph().getEndpoints(e); + V b = p.getFirst(); + V f = p.getSecond(); + Point2D pb = transformer.transform(layout.apply(b)); + Point2D pf = transformer.transform(layout.apply(f)); + float xB = (float) pb.getX(); + float yB = (float) pb.getY(); + float xF = (float) pf.getX(); + float yF = (float) pf.getY(); + if ((layout.getGraph().getEdgeType(e)) == EdgeType.UNDIRECTED) { + xF = (xF + xB) / 2; + yF = (yF + yB) / 2; + } + if(selfLoop.apply(Context.,E>getInstance(layout.getGraph(), e))) { + yF += 50; + xF += 50; + } + + return new GradientPaint(xB, yB, getColor1(e), xF, yF, getColor2(e), true); + } + + /** + * Returns c1. Subclasses may override + * this method to enable more complex behavior (e.g., for + * picked edges). + * @param e the edge for which a color is to be retrieved + * @return the constructor-supplied color {@code c1} + */ + protected Color getColor1(E e) + { + return c1; + } + + /** + * Returns c2. Subclasses may override + * this method to enable more complex behavior (e.g., for + * picked edges). + * @param e the edge for which a color is to be retrieved + * @return the constructor-supplied color {@code c2} + */ + protected Color getColor2(E e) + { + return c2; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/InterpolatingVertexSizeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/InterpolatingVertexSizeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/InterpolatingVertexSizeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/InterpolatingVertexSizeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Created on Nov 3, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import com.google.common.base.Function; + + +/** + * Provides vertex sizes that are spaced proportionally between + * min_size and max_size depending on + * + * @author Joshua O'Madadhain + */ +public class InterpolatingVertexSizeTransformer implements Function +{ + protected double min; + protected double max; + protected Function values; + protected int min_size; + protected int size_diff; + + public InterpolatingVertexSizeTransformer(Function values, + int min_size, int max_size) + { + super(); + if (min_size < 0 || max_size < 0) + throw new IllegalArgumentException("sizes must be non-negative"); + if (min_size > max_size) + throw new IllegalArgumentException("min_size must be <= max_size"); + this.min = 0; + this.max = 0; + this.values = values; + setMinSize(min_size); + setMaxSize(max_size); + } + + public Integer apply(V v) + { + Number n = values.apply(v); + double value = min; + if (n != null) + value = n.doubleValue(); + min = Math.min(this.min, value); + max = Math.max(this.max, value); + + if (min == max) + return min_size; + + // interpolate between min and max sizes based on how big value is + // with respect to min and max values + return min_size + (int)(((value - min) / (max - min)) * size_diff); + } + + public void setMinSize(int min_size) + { + this.min_size = min_size; + } + + public void setMaxSize(int max_size) + { + this.size_diff = max_size - this.min_size; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/NumberFormattingTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/NumberFormattingTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/NumberFormattingTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/NumberFormattingTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Created on Feb 16, 2009 + * + * Copyright (c) 2009, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.text.NumberFormat; + +import com.google.common.base.Function; + +/** + * Transforms inputs to String representations by chaining an input + * {@code Number}-generating {@code Function} with an internal + * {@code NumberFormat} instance. + * @author Joshua O'Madadhain + */ +public class NumberFormattingTransformer implements Function +{ + private Function values; + private NumberFormat formatter = NumberFormat.getInstance(); + + public NumberFormattingTransformer(Function values) + { + this.values = values; + } + + /** + * Returns a formatted string for the input. + */ + public String apply(T input) + { + return formatter.format(values.apply(input)); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + + + +

        Mechanisms for associating data (shapes, colors, values, strings, etc.) with +graph elements. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ParallelEdgeShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ParallelEdgeShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ParallelEdgeShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ParallelEdgeShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on March 10, 2005 + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Shape; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; + + +/** + * An abstract class for edge-to-Shape functions that work with parallel edges. + * + * @author Tom Nelson + */ +public abstract class ParallelEdgeShapeTransformer implements Function { + /** Specifies the distance between control points for edges being drawn in parallel. */ + protected float control_offset_increment = 20.f; + protected EdgeIndexFunction edgeIndexFunction; + + public void setControlOffsetIncrement(float y) { + control_offset_increment = y; + } + + public void setEdgeIndexFunction(EdgeIndexFunction edgeIndexFunction) { + this.edgeIndexFunction = edgeIndexFunction; + } + + public EdgeIndexFunction getEdgeIndexFunction() { + return edgeIndexFunction; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableEdgePaintTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableEdgePaintTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableEdgePaintTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableEdgePaintTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * Created on Mar 10, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Paint; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.visualization.picking.PickedInfo; + +/** + * Paints each edge according to the Paint + * parameters given in the constructor, so that picked and + * non-picked edges can be made to look different. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + * + */ +public class PickableEdgePaintTransformer implements Function { + protected PickedInfo pi; + protected Paint draw_paint; + protected Paint picked_paint; + + /** + * + * @param pi specifies which vertices report as "picked" + * @param draw_paint Paint used to draw edge shapes + * @param picked_paint Paint used to draw picked edge shapes + */ + public PickableEdgePaintTransformer(PickedInfo pi, Paint draw_paint, Paint picked_paint) { + if (pi == null) + throw new IllegalArgumentException("PickedInfo instance must be non-null"); + this.pi = pi; + this.draw_paint = draw_paint; + this.picked_paint = picked_paint; + } + + /** + * + */ + public Paint apply(E e) { + if (pi.isPicked(e)) { + return picked_paint; + } + else { + return draw_paint; + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexIconTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexIconTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexIconTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexIconTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* +* Created on Mar 10, 2005 +* +* Copyright (c) 2005, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization.decorators; + +import javax.swing.Icon; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.visualization.picking.PickedInfo; + +/** + * Supplies an Icon for each vertex according to the Icon + * parameters given in the constructor, so that picked and + * non-picked vertices can be made to look different. + */ +public class PickableVertexIconTransformer implements Function { + + protected Icon icon; + protected Icon picked_icon; + protected PickedInfo pi; + + /** + * + * @param pi specifies which vertices report as "picked" + * @param icon Icon used to represent vertices + * @param picked_icon Icon used to represent picked vertices + */ + public PickableVertexIconTransformer(PickedInfo pi, Icon icon, Icon picked_icon) + { + if (pi == null) + throw new IllegalArgumentException("PickedInfo instance must be non-null"); + this.pi = pi; + this.icon = icon; + this.picked_icon = picked_icon; + } + + /** + * Returns the appropriate Icon, depending on picked state. + */ + public Icon apply(V v) { + if (pi.isPicked(v)) + return picked_icon; + else + return icon; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexPaintTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexPaintTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexPaintTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/PickableVertexPaintTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +/* +* Created on Mar 10, 2005 +* +* Copyright (c) 2005, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Paint; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.visualization.picking.PickedInfo; + +/** + * Paints each vertex according to the Paint + * parameters given in the constructor, so that picked and + * non-picked vertices can be made to look different. + */ +public class PickableVertexPaintTransformer implements Function { + + protected Paint fill_paint; + protected Paint picked_paint; + protected PickedInfo pi; + + /** + * + * @param pi specifies which vertices report as "picked" + * @param fill_paint Paint used to fill vertex shapes + * @param picked_paint Paint used to fill picked vertex shapes + */ + public PickableVertexPaintTransformer(PickedInfo pi, + Paint fill_paint, Paint picked_paint) + { + if (pi == null) + throw new IllegalArgumentException("PickedInfo instance must be non-null"); + this.pi = pi; + this.fill_paint = fill_paint; + this.picked_paint = picked_paint; + } + + public Paint apply(V v) + { + if (pi.isPicked(v)) + return picked_paint; + else + return fill_paint; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/SettableVertexShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/SettableVertexShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/SettableVertexShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/SettableVertexShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Created on Jul 18, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Shape; + +import com.google.common.base.Function; + + + +/** + * + * @author Joshua O'Madadhain + */ +public interface SettableVertexShapeTransformer extends Function +{ + public abstract void setSizeTransformer(Function vsf); + + public abstract void setAspectRatioTransformer(Function varf); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ToStringLabeller.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ToStringLabeller.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ToStringLabeller.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/ToStringLabeller.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Apr 13, 2004 + */ +package edu.uci.ics.jung.visualization.decorators; + +import com.google.common.base.Function; + + + +/** + * Labels vertices by their toString. This class functions as a drop-in + * replacement for the default StringLabeller method. This class does not + * guarantee unique labels; or even consistent ones. + * + * @author danyelf + */ +public class ToStringLabeller implements Function { + + /** + * @return o.toString() + */ + public String apply(Object o) { + return o.toString(); + } + + } \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/VertexIconShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/VertexIconShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/VertexIconShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/decorators/VertexIconShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 1, 2005 + */ + +package edu.uci.ics.jung.visualization.decorators; + +import java.awt.Image; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.Icon; +import javax.swing.ImageIcon; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.visualization.util.ImageShapeUtils; + +/** + * A default implementation that stores images in a Map keyed on the + * vertex. Also applies a shaping function to images to extract the + * shape of the opaque part of a transparent image. + * + * @author Tom Nelson + */ +public class VertexIconShapeTransformer implements Function { + protected Map shapeMap = new HashMap(); + protected Map iconMap; + protected Function delegate; + + /** + * Creates an instance with the specified delegate. + * @param delegate the vertex-to-shape function to use if no image is present for the vertex + */ + public VertexIconShapeTransformer(Function delegate) { + this.delegate = delegate; + } + + /** + * @return Returns the delegate. + */ + public Function getDelegate() { + return delegate; + } + + /** + * @param delegate The delegate to set. + */ + public void setDelegate(Function delegate) { + this.delegate = delegate; + } + + /** + * get the shape from the image. If not available, get + * the shape from the delegate VertexShapeFunction + */ + public Shape apply(V v) { + Icon icon = iconMap.get(v); + if (icon != null && icon instanceof ImageIcon) { + Image image = ((ImageIcon) icon).getImage(); + Shape shape = (Shape) shapeMap.get(image); + if (shape == null) { + shape = ImageShapeUtils.getShape(image, 30); + if(shape.getBounds().getWidth() > 0 && + shape.getBounds().getHeight() > 0) { + // don't cache a zero-sized shape, wait for the image + // to be ready + int width = image.getWidth(null); + int height = image.getHeight(null); + AffineTransform transform = AffineTransform + .getTranslateInstance(-width / 2, -height / 2); + shape = transform.createTransformedShape(shape); + shapeMap.put(image, shape); + } + } + return shape; + } else { + return delegate.apply(v); + } + } + + /** + * @return the iconMap + */ + public Map getIconMap() { + return iconMap; + } + + /** + * @param iconMap the iconMap to set + */ + public void setIconMap(Map iconMap) { + this.iconMap = iconMap; + } + + /** + * @return the shapeMap + */ + public Map getShapeMap() { + return shapeMap; + } + + /** + * @param shapeMap the shapeMap to set + */ + public void setShapeMap(Map shapeMap) { + this.shapeMap = shapeMap; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/DefaultVisualizationModel.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/DefaultVisualizationModel.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/DefaultVisualizationModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/DefaultVisualizationModel.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,188 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization; + +import java.awt.Dimension; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.algorithms.layout.util.VisRunner; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.visualization.layout.ObservableCachingLayout; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; +import edu.uci.ics.jung.visualization.util.DefaultChangeEventSupport; + +/** + * The model containing state values for + * visualizations of graphs. + * Refactored and extracted from the 1.6.0 version of VisualizationViewer + * + * @author Tom Nelson + */ +public class DefaultVisualizationModel implements VisualizationModel, ChangeEventSupport { + + ChangeEventSupport changeSupport = new DefaultChangeEventSupport(this); + + /** + * manages the thread that applies the current layout algorithm + */ + protected Relaxer relaxer; + + /** + * the layout algorithm currently in use + */ + protected Layout layout; + + /** + * listens for changes in the layout, forwards to the viewer + * + */ + protected ChangeListener changeListener; + + /** + * + * @param layout The Layout to apply, with its associated Graph + */ + public DefaultVisualizationModel(Layout layout) { + this(layout, null); + } + + /** + * Create an instance with the specified layout and dimension. + * @param layout the layout to use + * @param d The preferred size of the View that will display this graph + */ + public DefaultVisualizationModel(Layout layout, Dimension d) { + if(changeListener == null) { + changeListener = new ChangeListener() { + public void stateChanged(ChangeEvent e) { + fireStateChanged(); + } + }; + } + setGraphLayout(layout, d); + } + + /** + * Removes the current graph layout, and adds a new one. + * @param layout the new layout to use + * @param viewSize the size of the View that will display this layout + */ + public void setGraphLayout(Layout layout, Dimension viewSize) { + // remove listener from old layout + if(this.layout != null && this.layout instanceof ChangeEventSupport) { + ((ChangeEventSupport)this.layout).removeChangeListener(changeListener); + } + // set to new layout + if(layout instanceof ChangeEventSupport) { + this.layout = layout; + } else { + this.layout = new ObservableCachingLayout(layout); + } + + ((ChangeEventSupport)this.layout).addChangeListener(changeListener); + + if(viewSize == null) { + viewSize = new Dimension(600,600); + } + Dimension layoutSize = layout.getSize(); + // if the layout has NOT been initialized yet, initialize its size + // now to the size of the VisualizationViewer window + if(layoutSize == null) { + layout.setSize(viewSize); + } + if(relaxer != null) { + relaxer.stop(); + relaxer = null; + } + if(layout instanceof IterativeContext) { + layout.initialize(); + if(relaxer == null) { + relaxer = new VisRunner((IterativeContext)this.layout); + relaxer.prerelax(); + relaxer.relax(); + } + } + fireStateChanged(); + } + + /** + * set the graph Layout and if it is not already initialized, initialize + * it to the default VisualizationViewer preferred size of 600x600 + */ + public void setGraphLayout(Layout layout) { + setGraphLayout(layout, null); + } + + /** + * Returns the current graph layout. + */ + public Layout getGraphLayout() { + return layout; + } + + /** + * @return the relaxer + */ + public Relaxer getRelaxer() { + return relaxer; + } + + /** + * @param relaxer the relaxer to set + */ + public void setRelaxer(VisRunner relaxer) { + this.relaxer = relaxer; + } + + /** + * Adds a ChangeListener. + * @param l the listener to be added + */ + public void addChangeListener(ChangeListener l) { + changeSupport.addChangeListener(l); + } + + /** + * Removes a ChangeListener. + * @param l the listener to be removed + */ + public void removeChangeListener(ChangeListener l) { + changeSupport.removeChangeListener(l); + } + + /** + * Returns an array of all the ChangeListeners added + * with addChangeListener(). + * + * @return all of the ChangeListeners added or an empty + * array if no listeners have been added + */ + public ChangeListener[] getChangeListeners() { + return changeSupport.getChangeListeners(); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * The primary listeners will be views that need to be repainted + * because of changes in this model instance + * @see EventListenerList + */ + public void fireStateChanged() { + changeSupport.fireStateChanged(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/FourPassImageShaper.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/FourPassImageShaper.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/FourPassImageShaper.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/FourPassImageShaper.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jun 17, 2005 + */ + +package edu.uci.ics.jung.visualization; + +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; + +/** + * Provides Supplier methods that, given a BufferedImage, an Image, + * or the fileName of an image, will return a java.awt.Shape that + * is the contiguous traced outline of the opaque part of the image. + * This could be used to define an image for use in a Vertex, where + * the shape used for picking and edge-arrow placement follows the + * opaque part of an image that has a transparent background. + * The methods try to detect lines in order to minimize points + * in the path + * + * @author Tom Nelson + * + * + */ +public class FourPassImageShaper { + + public static Shape getShape(BufferedImage image) { + Area area = new Area(leftEdge(image)); + area.intersect(new Area(bottomEdge(image))); + area.intersect(new Area(rightEdge(image))); + area.intersect(new Area(topEdge(image))); + return area; + } + /** + * Checks to see if point p is on a line that passes thru + * points p1 and p2. If p is on the line, extend the line + * segment so that it is from p1 to the location of p. + * If the point p is not on the line, update my shape + * with a line extending to the old p2 location, make + * the old p2 the new p1, and make p2 the old p + * @param p1 + * @param p2 + * @param p + * @param line + * @param path + * @return + */ + private static Point2D detectLine(Point2D p1, Point2D p2, Point2D p, + Line2D line, GeneralPath path) { + + // check for line + // if p is on the line that extends thru p1 and p2 + if(line.ptLineDistSq(p) == 0) { // p is on the line p1,p2 + // extend line so that p2 is at p + p2.setLocation(p); + } else { // its not on the current line + // start a new line from p2 to p + p1.setLocation(p2); + p2.setLocation(p); + line.setLine(p1,p2); + // end the ongoing path line at the new p1 (the old p2) + path.lineTo((float)p1.getX(), (float)p1.getY()); + } + return p2; + } + /** + * trace the left side of the image + * @param image + * @param path + * @return + */ + private static Shape leftEdge(BufferedImage image) { + GeneralPath path = new GeneralPath(); + Point2D p1 = null; + Point2D p2 = null; + Line2D line = new Line2D.Float(); + Point2D p = new Point2D.Float(); + int foundPointY = -1; + for(int i=0; i= 0) { + if(p2 == null) { + // this is the first point found. project line to right edge + p1 = new Point2D.Float(image.getWidth()-1, foundPointY); + path.moveTo(p1.getX(), p1.getY()); + p2 = new Point2D.Float(); + p2.setLocation(p); + } else { + p2 = detectLine(p1, p2, p, line, path); + } + } + } + path.lineTo(p.getX(), p.getY()); + if(foundPointY >= 0) { + path.lineTo(image.getWidth()-1, foundPointY); + } + path.closePath(); + return path; + } + + /** + * trace the bottom of the image + * @param image + * @param path + * @param start + * @return + */ + private static Shape bottomEdge(BufferedImage image) { + GeneralPath path = new GeneralPath(); + Point2D p1 = null; + Point2D p2 = null; + Line2D line = new Line2D.Float(); + Point2D p = new Point2D.Float(); + int foundPointX = -1; + for(int i=0; i=0; j--) { + if((image.getRGB(i,j) & 0xff000000) != 0) { + // this is a point I want + p.setLocation(i,j); + foundPointX = i; + break; + } + } + if(foundPointX >= 0) { + if(p2 == null) { + // this is the first point found. project line to top edge + p1 = new Point2D.Float(foundPointX, 0); + // path starts here + path.moveTo(p1.getX(), p1.getY()); + p2 = new Point2D.Float(); + p2.setLocation(p); + } else { + p2 = detectLine(p1, p2, p, line, path); + } + } + } + path.lineTo(p.getX(), p.getY()); + if(foundPointX >= 0) { + path.lineTo(foundPointX, 0); + } + path.closePath(); + return path; + } + + /** + * trace the right side of the image + * @param image + * @param path + * @param start + * @return + */ + private static Shape rightEdge(BufferedImage image) { + GeneralPath path = new GeneralPath(); + Point2D p1 = null; + Point2D p2 = null; + Line2D line = new Line2D.Float(); + Point2D p = new Point2D.Float(); + int foundPointY = -1; + + for(int i=image.getHeight()-1; i>=0; i--) { + for(int j=image.getWidth()-1; j>=0; j--) { + if((image.getRGB(j,i) & 0xff000000) != 0) { + // this is a point I want + p.setLocation(j,i); + foundPointY = i; + break; + } + } + if(foundPointY >= 0) { + if(p2 == null) { + // this is the first point found. project line to top edge + p1 = new Point2D.Float(0, foundPointY); + // path starts here + path.moveTo(p1.getX(), p1.getY()); + p2 = new Point2D.Float(); + p2.setLocation(p); + } else { + p2 = detectLine(p1, p2, p, line, path); + } + } + } + path.lineTo(p.getX(), p.getY()); + if(foundPointY >= 0) { + path.lineTo(0, foundPointY); + } + path.closePath(); + return path; + } + + /** + * trace the top of the image + * @param image + * @param path + * @param start + * @return + */ + private static Shape topEdge(BufferedImage image) { + GeneralPath path = new GeneralPath(); + Point2D p1 = null; + Point2D p2 = null; + Line2D line = new Line2D.Float(); + Point2D p = new Point2D.Float(); + int foundPointX = -1; + + for(int i=image.getWidth()-1; i>=0; i--) { + for(int j=0; j= 0) { + if(p2 == null) { + // this is the first point found. project line to top edge + p1 = new Point2D.Float(foundPointX, image.getHeight()-1); + // path starts here + path.moveTo(p1.getX(), p1.getY()); + p2 = new Point2D.Float(); + p2.setLocation(p); + } else { + p2 = detectLine(p1, p2, p, line, path); + } + } + } + path.lineTo(p.getX(), p.getY()); + if(foundPointX >= 0) { + path.lineTo(foundPointX, image.getHeight()-1); + } + path.closePath(); + return path; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/GraphZoomScrollPane.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/GraphZoomScrollPane.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/GraphZoomScrollPane.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/GraphZoomScrollPane.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Feb 2, 2005 + * + */ +package edu.uci.ics.jung.visualization; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Set; + +import javax.swing.BoundedRangeModel; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; +import edu.uci.ics.jung.visualization.transform.shape.Intersector; + + + +/** + * GraphZoomScrollPane is a Container for the Graph's VisualizationViewer + * and includes custom horizontal and vertical scrollbars. + * GraphZoomScrollPane listens for changes in the scale and + * translation of the VisualizationViewer, and will update the + * scrollbar positions and sizes accordingly. Changes in the + * scrollbar positions will cause the corresponding change in + * the translation component (offset) of the VisualizationViewer. + * The scrollbars are modified so that they will allow panning + * of the graph when the scale has been changed (e.g. zoomed-in + * or zoomed-out). + * + * The lower-right corner of this component is available to + * use as a small button or menu. + * + * samples.graph.GraphZoomScrollPaneDemo shows the use of this component. + * + * @author Tom Nelson + * + * + */ +@SuppressWarnings("serial") +public class GraphZoomScrollPane extends JPanel { + protected VisualizationViewer vv; + protected JScrollBar horizontalScrollBar; + protected JScrollBar verticalScrollBar; + protected JComponent corner; + protected boolean scrollBarsMayControlAdjusting = true; + protected JPanel south; + + /** + * Create an instance of the GraphZoomScrollPane to contain the + * VisualizationViewer + * @param vv the VisualizationViewer for which this instance is to be created + */ + public GraphZoomScrollPane(VisualizationViewer vv) { + super(new BorderLayout()); + this.vv = vv; + addComponentListener(new ResizeListener()); + Dimension d = vv.getGraphLayout().getSize(); + verticalScrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, d.height, 0, d.height); + horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, d.width, 0, d.width); + verticalScrollBar.addAdjustmentListener(new VerticalAdjustmentListenerImpl()); + horizontalScrollBar.addAdjustmentListener(new HorizontalAdjustmentListenerImpl()); + verticalScrollBar.setUnitIncrement(20); + horizontalScrollBar.setUnitIncrement(20); + // respond to changes in the VisualizationViewer's transform + // and set the scroll bar parameters appropriately + vv.addChangeListener( + new ChangeListener(){ + public void stateChanged(ChangeEvent evt) { + VisualizationViewer vv = + (VisualizationViewer)evt.getSource(); + setScrollBars(vv); + } + }); + add(vv); + add(verticalScrollBar, BorderLayout.EAST); + south = new JPanel(new BorderLayout()); + south.add(horizontalScrollBar); + setCorner(new JPanel()); + add(south, BorderLayout.SOUTH); + } + + /** + * listener for adjustment of the horizontal scroll bar. + * Sets the translation of the VisualizationViewer + */ + class HorizontalAdjustmentListenerImpl implements AdjustmentListener { + int previous = 0; + public void adjustmentValueChanged(AdjustmentEvent e) { + int hval = e.getValue(); + float dh = previous - hval; + previous = hval; + if(dh != 0 && scrollBarsMayControlAdjusting) { + // get the uniform scale of all transforms + float layoutScale = (float) vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale(); + dh *= layoutScale; + AffineTransform at = AffineTransform.getTranslateInstance(dh, 0); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).preConcatenate(at); + } + } + } + + /** + * Listener for adjustment of the vertical scroll bar. + * Sets the translation of the VisualizationViewer + */ + class VerticalAdjustmentListenerImpl implements AdjustmentListener { + int previous = 0; + public void adjustmentValueChanged(AdjustmentEvent e) { + JScrollBar sb = (JScrollBar)e.getSource(); + BoundedRangeModel m = sb.getModel(); + int vval = m.getValue(); + float dv = previous - vval; + previous = vval; + if(dv != 0 && scrollBarsMayControlAdjusting) { + + // get the uniform scale of all transforms + float layoutScale = (float) vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale(); + dv *= layoutScale; + AffineTransform at = AffineTransform.getTranslateInstance(0, dv); + vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).preConcatenate(at); + } + } + } + + /** + * use the supplied vv characteristics to set the position and + * dimensions of the scroll bars. Called in response to + * a ChangeEvent from the VisualizationViewer + * @param xform the transform of the VisualizationViewer + */ + private void setScrollBars(VisualizationViewer vv) { + Dimension d = vv.getGraphLayout().getSize(); + Rectangle2D vvBounds = vv.getBounds(); + + // a rectangle representing the layout + Rectangle layoutRectangle = + new Rectangle(0,0,d.width,d.height); + //-d.width/2, -d.height/2, 2*d.width, 2*d.height); + + BidirectionalTransformer viewTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW); + BidirectionalTransformer layoutTransformer = vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT); + + Point2D h0 = new Point2D.Double(vvBounds.getMinX(), vvBounds.getCenterY()); + Point2D h1 = new Point2D.Double(vvBounds.getMaxX(), vvBounds.getCenterY()); + Point2D v0 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMinY()); + Point2D v1 = new Point2D.Double(vvBounds.getCenterX(), vvBounds.getMaxY()); + + h0 = viewTransformer.inverseTransform(h0); + h0 = layoutTransformer.inverseTransform(h0); + h1 = viewTransformer.inverseTransform(h1); + h1 = layoutTransformer.inverseTransform(h1); + v0 = viewTransformer.inverseTransform(v0); + v0 = layoutTransformer.inverseTransform(v0); + v1 = viewTransformer.inverseTransform(v1); + v1 = layoutTransformer.inverseTransform(v1); + + scrollBarsMayControlAdjusting = false; + setScrollBarValues(layoutRectangle, h0, h1, v0, v1); + scrollBarsMayControlAdjusting = true; + } + + protected void setScrollBarValues(Rectangle rectangle, + Point2D h0, Point2D h1, + Point2D v0, Point2D v1) { + boolean containsH0 = rectangle.contains(h0); + boolean containsH1 = rectangle.contains(h1); + boolean containsV0 = rectangle.contains(v0); + boolean containsV1 = rectangle.contains(v1); + + // horizontal scrollbar: + + Intersector intersector = new Intersector(rectangle, new Line2D.Double(h0, h1)); + + int min = 0; + int ext; + int val = 0; + int max; + + Set points = intersector.getPoints(); + Point2D first = null; + Point2D second = null; + + Point2D[] pointArray = (Point2D[])points.toArray(new Point2D[points.size()]); + if(pointArray.length > 1) { + first = pointArray[0]; + second = pointArray[1]; + } else if(pointArray.length > 0) { + first = second = pointArray[0]; + } + + if(first != null && second != null) { + // correct direction of intersect points + if((h0.getX() - h1.getX()) * (first.getX() - second.getX()) < 0) { + // swap them + Point2D temp = first; + first = second; + second = temp; + } + + if(containsH0 && containsH1) { + max = (int)first.distance(second); + val = (int)first.distance(h0); + ext = (int)h0.distance(h1); + + } else if(containsH0) { + max = (int)first.distance(second); + val = (int)first.distance(h0); + ext = (int)h0.distance(second); + + } else if(containsH1) { + max = (int) first.distance(second); + val = 0; + ext = (int) first.distance(h1); + + } else { + max = ext = rectangle.width; + val = min; + } + horizontalScrollBar.setValues(val, ext+1, min, max); + } + + // vertical scroll bar + min = val = 0; + + intersector.intersectLine(new Line2D.Double(v0, v1)); + points = intersector.getPoints(); + + pointArray = (Point2D[])points.toArray(new Point2D[points.size()]); + if(pointArray.length > 1) { + first = pointArray[0]; + second = pointArray[1]; + } else if(pointArray.length > 0) { + first = second = pointArray[0]; + } + + if(first != null && second != null) { + + // arrange for direction + if((v0.getY() - v1.getY()) * (first.getY() - second.getY()) < 0) { + // swap them + Point2D temp = first; + first = second; + second = temp; + } + + if(containsV0 && containsV1) { + max = (int)first.distance(second); + val = (int)first.distance(v0); + ext = (int)v0.distance(v1); + + } else if(containsV0) { + max = (int)first.distance(second); + val = (int)first.distance(v0); + ext = (int)v0.distance(second); + + } else if(containsV1) { + max = (int) first.distance(second); + val = 0; + ext = (int) first.distance(v1); + + } else { + max = ext = rectangle.height; + val = min; + } + verticalScrollBar.setValues(val, ext+1, min, max); + } + } + + /** + * Listener to adjust the scroll bar parameters when the window + * is resized + */ + protected class ResizeListener extends ComponentAdapter { + + public void componentHidden(ComponentEvent e) { + } + + public void componentResized(ComponentEvent e) { + setScrollBars(vv); + } + public void componentShown(ComponentEvent e) { + } + } + + /** + * @return Returns the corner component. + */ + public JComponent getCorner() { + return corner; + } + + /** + * @param corner The cornerButton to set. + */ + public void setCorner(JComponent corner) { + this.corner = corner; + corner.setPreferredSize(new Dimension(verticalScrollBar.getPreferredSize().width, + horizontalScrollBar.getPreferredSize().height)); + south.add(this.corner, BorderLayout.EAST); + } + + public JScrollBar getHorizontalScrollBar() { + return horizontalScrollBar; + } + + public JScrollBar getVerticalScrollBar() { + return verticalScrollBar; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/LayeredIcon.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/LayeredIcon.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/LayeredIcon.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/LayeredIcon.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,48 @@ +package edu.uci.ics.jung.visualization; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.swing.Icon; +import javax.swing.ImageIcon; + +/** + * An icon that is made up of a collection of Icons. + * They are rendered in layers starting with the first + * Icon added (from the constructor). + * + * @author Tom Nelson + * + */ +@SuppressWarnings("serial") +public class LayeredIcon extends ImageIcon { + + Set iconSet = new LinkedHashSet(); + + public LayeredIcon(Image image) { + super(image); + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + super.paintIcon(c, g, x, y); + Dimension d = new Dimension(getIconWidth(), getIconHeight()); + for (Icon icon : iconSet) { + Dimension id = new Dimension(icon.getIconWidth(), icon.getIconHeight()); + int dx = (d.width - id.width)/2; + int dy = (d.height - id.height)/2; + icon.paintIcon(c, g, x+dx, y+dy); + } + } + + public void add(Icon icon) { + iconSet.add(icon); + } + + public boolean remove(Icon icon) { + return iconSet.remove(icon); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/Layer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/Layer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/Layer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/Layer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,5 @@ +package edu.uci.ics.jung.visualization; + +public enum Layer { + LAYOUT, VIEW +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectangleCollector.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectangleCollector.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectangleCollector.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectangleCollector.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,86 @@ +package edu.uci.ics.jung.visualization.layout; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.RenderContext; + +public class BoundingRectangleCollector { + + protected RenderContext rc; + protected Graph graph; + protected Layout layout; + protected List rectangles = new ArrayList(); + + public BoundingRectangleCollector(RenderContext rc, Layout layout) { + this.rc = rc; + this.layout = layout; + this.graph = layout.getGraph(); + compute(); + } + + /** + * @return the rectangles + */ + public List getRectangles() { + return rectangles; + } + + public void compute() { + rectangles.clear(); +// Graphics2D g2d = (Graphics2D)g; +// g.setColor(Color.cyan); + + for(E e : graph.getEdges()) { + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + float x1 = (float)p1.getX(); + float y1 = (float)p1.getY(); + float x2 = (float)p2.getX(); + float y2 = (float)p2.getY(); + + boolean isLoop = v1.equals(v2); + Shape s2 = rc.getVertexShapeTransformer().apply(v2); + Shape edgeShape = rc.getEdgeShapeTransformer().apply(e); + + AffineTransform xform = AffineTransform.getTranslateInstance(x1,y1); + + if(isLoop) { + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(), s2Bounds.getHeight()); + xform.translate(0, -edgeShape.getBounds2D().getWidth()/2); + } else { + float dx = x2-x1; + float dy = y2-y1; + float theta = (float)Math.atan2(dy,dx); + xform.rotate(theta); + float dist = (float)p1.distance(p2); + xform.scale(dist, 1.0); + } + edgeShape = xform.createTransformedShape(edgeShape); +// edgeShape = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, edgeShape); + rectangles.add(edgeShape.getBounds2D()); + } + + for(V v : graph.getVertices()) { + Shape shape = rc.getVertexShapeTransformer().apply(v); + Point2D p = layout.apply(v); +// p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); + float x = (float)p.getX(); + float y = (float)p.getY(); + AffineTransform xform = AffineTransform.getTranslateInstance(x, y); + shape = xform.createTransformedShape(shape); + rectangles.add(shape.getBounds2D()); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectanglePaintable.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectanglePaintable.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectanglePaintable.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/BoundingRectanglePaintable.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,56 @@ +package edu.uci.ics.jung.visualization.layout; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.util.List; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; + +public class BoundingRectanglePaintable implements VisualizationServer.Paintable { + + protected RenderContext rc; + protected Graph graph; + protected Layout layout; + protected List rectangles; + + public BoundingRectanglePaintable(RenderContext rc, Layout layout) { + super(); + this.rc = rc; + this.layout = layout; + this.graph = layout.getGraph(); + final BoundingRectangleCollector brc = new BoundingRectangleCollector(rc, layout); + this.rectangles = brc.getRectangles(); + if(layout instanceof ChangeEventSupport) { + ((ChangeEventSupport)layout).addChangeListener(new ChangeListener() { + + public void stateChanged(ChangeEvent e) { + brc.compute(); + rectangles = brc.getRectangles(); + }}); + } + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g.setColor(Color.cyan); + + for(Rectangle2D r : rectangles) { + g2d.draw(rc.getMultiLayerTransformer().transform(Layer.LAYOUT, r)); + } + } + + public boolean useTransform() { + return true; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/CachingLayout.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/CachingLayout.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/CachingLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/CachingLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ + +package edu.uci.ics.jung.visualization.layout; + +import java.awt.geom.Point2D; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.LayoutDecorator; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.visualization.util.Caching; + +/** + * A LayoutDecorator that caches locations in a clearable Map. This can be used to ensure that + * edge endpoints are always the same as vertex locations when they are drawn in the render loop + * during the time that the layout's relaxer thread is changing the locations. + * + * @see LayoutDecorator + * @author Tom Nelson + * + */ +public class CachingLayout extends LayoutDecorator implements Caching { + + protected LoadingCache locations; + + public CachingLayout(Layout delegate) { + super(delegate); + Function chain = Functions.compose( + new Function() { + public Point2D apply(Point2D p) { + return (Point2D)p.clone(); + }}, + delegate); + this.locations = CacheBuilder.newBuilder().build(CacheLoader.from(chain)); + } + + @Override + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } + + public void clear() { + this.locations = CacheBuilder.newBuilder().build(new CacheLoader() { + public Point2D load(V vertex) { + return new Point2D.Double(); + } + }); + } + + public void init() { + } + + public Point2D apply(V v) { + return locations.getUnchecked(v); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutChangeListener.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutChangeListener.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutChangeListener.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutChangeListener.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,7 @@ +package edu.uci.ics.jung.visualization.layout; + +public interface LayoutChangeListener { + + void layoutChanged(LayoutEvent evt); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEvent.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEvent.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEvent.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,26 @@ +package edu.uci.ics.jung.visualization.layout; + +import edu.uci.ics.jung.graph.Graph; + +public class LayoutEvent { + + V vertex; + Graph graph; + + public LayoutEvent(V vertex, Graph graph) { + this.vertex = vertex; + this.graph = graph; + } + public V getVertex() { + return vertex; + } + public void setVertex(V vertex) { + this.vertex = vertex; + } + public Graph getGraph() { + return graph; + } + public void setGraph(Graph graph) { + this.graph = graph; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEventSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEventSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEventSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutEventSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,9 @@ +package edu.uci.ics.jung.visualization.layout; + +public interface LayoutEventSupport { + + void addLayoutChangeListener(LayoutChangeListener listener); + + void removeLayoutChangeListener(LayoutChangeListener listener); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutTransition.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutTransition.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutTransition.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/LayoutTransition.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,57 @@ +package edu.uci.ics.jung.visualization.layout; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.StaticLayout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.algorithms.layout.util.VisRunner; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.visualization.VisualizationViewer; + +public class LayoutTransition implements IterativeContext { + + protected Layout startLayout; + protected Layout endLayout; + protected Layout transitionLayout; + protected boolean done = false; + protected int count = 20; + protected int counter = 0; + protected VisualizationViewer vv; + + public LayoutTransition(VisualizationViewer vv, Layout startLayout, Layout endLayout) { + this.vv = vv; + this.startLayout = startLayout; + this.endLayout = endLayout; + if(endLayout instanceof IterativeContext) { + Relaxer relaxer = new VisRunner((IterativeContext)endLayout); + relaxer.prerelax(); + } + this.transitionLayout = + new StaticLayout(startLayout.getGraph(), startLayout); + vv.setGraphLayout(transitionLayout); + } + + public boolean done() { + return done; + } + + public void step() { + Graph g = transitionLayout.getGraph(); + for(V v : g.getVertices()) { + Point2D tp = transitionLayout.apply(v); + Point2D fp = endLayout.apply(v); + double dx = (fp.getX()-tp.getX())/(count-counter); + double dy = (fp.getY()-tp.getY())/(count-counter); + transitionLayout.setLocation(v, + new Point2D.Double(tp.getX()+dx,tp.getY()+dy)); + } + counter++; + if(counter >= count) { + done = true; + vv.setGraphLayout(endLayout); + } + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/ObservableCachingLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ + +package edu.uci.ics.jung.visualization.layout; + +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.event.ChangeListener; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.LayoutDecorator; +import edu.uci.ics.jung.algorithms.util.IterativeContext; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.visualization.util.Caching; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; +import edu.uci.ics.jung.visualization.util.DefaultChangeEventSupport; + +/** + * A LayoutDecorator that fires ChangeEvents when certain methods + * are called. Used to wrap a Layout so that the visualization + * components can be notified of changes. + * + * @see LayoutDecorator + * @author Tom Nelson + * + */ +public class ObservableCachingLayout extends LayoutDecorator + implements ChangeEventSupport, Caching, LayoutEventSupport { + + protected ChangeEventSupport changeSupport = new DefaultChangeEventSupport(this); + + protected LoadingCache locations; + + private List> layoutChangeListeners = + new ArrayList>(); + + public ObservableCachingLayout(Layout delegate) { + super(delegate); + Function chain = Functions. compose( + new Function() { + public Point2D apply(Point2D p) { + return (Point2D) p.clone(); + } + }, + delegate); + this.locations = CacheBuilder.newBuilder().build(CacheLoader.from(chain)); + } + + @Override + public void step() { + super.step(); + fireStateChanged(); + } + + @Override + public void initialize() { + super.initialize(); + fireStateChanged(); + } + + @Override + public boolean done() { + if(delegate instanceof IterativeContext) { + return ((IterativeContext)delegate).done(); + } + return true; + } + + + @Override + public void setLocation(V v, Point2D location) { + super.setLocation(v, location); + fireStateChanged(); + fireLayoutChanged(v); + } + + public void addChangeListener(ChangeListener l) { + changeSupport.addChangeListener(l); + } + + public void removeChangeListener(ChangeListener l) { + changeSupport.removeChangeListener(l); + } + + public ChangeListener[] getChangeListeners() { + return changeSupport.getChangeListeners(); + } + + public void fireStateChanged() { + changeSupport.fireStateChanged(); + } + + @Override + public void setGraph(Graph graph) { + delegate.setGraph(graph); + } + + public void clear() { + this.locations.invalidateAll(); + } + + public void init() { + } + + public Point2D apply(V v) { + return locations.getUnchecked(v); + } + + private void fireLayoutChanged(V v) { + LayoutEvent evt = new LayoutEvent(v, this.getGraph()); + for(LayoutChangeListener listener : layoutChangeListeners) { + listener.layoutChanged(evt); + } + } + + public void addLayoutChangeListener(LayoutChangeListener listener) { + layoutChangeListeners.add(listener); + + } + + public void removeLayoutChangeListener(LayoutChangeListener listener) { + layoutChangeListeners.remove(listener); + + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,20 @@ + + + + + + + +

        Visualization mechanisms related to graph layout: caching, persistence, +event-emitting, etc. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayoutImpl.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayoutImpl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayoutImpl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayoutImpl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Oct 8, 2004 + * + */ +package edu.uci.ics.jung.visualization.layout; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.util.Caching; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; + + +/** + * Implementation of PersistentLayout. + * Defers to another layout until 'restore' is called, + * then it uses the saved vertex locations + * + * @author Tom Nelson + * + * + */ +public class PersistentLayoutImpl extends ObservableCachingLayout + implements PersistentLayout, ChangeEventSupport, Caching { + + /** + * a container for Vertices + */ + protected Map locations; + + /** + * a collection of Vertices that should not move + */ + protected Set dontmove; + + /** + * whether the graph is locked (stops the VisualizationViewer rendering thread) + */ + protected boolean locked; + + /** + * create an instance with a passed layout + * create containers for graph components + * @param layout the layout whose positions are to be persisted + */ + public PersistentLayoutImpl(Layout layout) { + super(layout); + this.locations = Maps.asMap( + ImmutableSet.copyOf(layout.getGraph().getVertices()), + new RandomPointFactory(getSize())); + this.dontmove = new HashSet(); + } + + /** + * This method calls initialize_local_vertex for each vertex, and + * also adds initial coordinate information for each vertex. (The vertex's + * initial location is set by calling initializeLocation. + */ + protected void initializeLocations() { + for(V v : getGraph().getVertices()) { + Point2D coord = delegate.apply(v); + if (!dontmove.contains(v)) + initializeLocation(v, coord); + } + } + + + /** + * Sets persisted location for a vertex within the dimensions of the space. + * If the vertex has not been persisted, sets a random location. If you want + * to initialize in some different way, override this method. + * + * @param v the vertex whose location is to be initialized + * @param coord the location + */ + protected void initializeLocation(V v, Point2D coord) { + Point point = locations.get(v); + coord.setLocation(point.x, point.y); + } + + /** + * save the Vertex locations to a file + * @param fileName the file to save to + * @throws IOException if the file cannot be used + */ + public void persist(String fileName) throws IOException { + + for(V v : getGraph().getVertices()) { + Point p = new Point(transform(v)); + locations.put(v, p); + } + ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( + fileName)); + oos.writeObject(locations); + oos.close(); + } + + /** + * Restore the graph Vertex locations from a file + * @param fileName the file to use + * @throws IOException for file problems + * @throws ClassNotFoundException for classpath problems + */ + @SuppressWarnings("unchecked") + public void restore(String fileName) throws IOException, + ClassNotFoundException { + ObjectInputStream ois = new ObjectInputStream(new FileInputStream( + fileName)); + locations = (Map) ois.readObject(); + ois.close(); + initializeLocations(); + locked = true; + fireStateChanged(); + } + + public void lock(boolean locked) { + this.locked = locked; + } + + /* + * (non-Javadoc) + * + * @see edu.uci.ics.jung.visualization.Layout#incrementsAreDone() + */ + public boolean done() { + return super.done() || locked; + } + + /* + * (non-Javadoc) + * + * @see edu.uci.ics.jung.visualization.Layout#lockVertex(edu.uci.ics.jung.graph.Vertex) + */ + public void lock(V v, boolean state) { + dontmove.add(v); + delegate.lock(v, state); + } + + @SuppressWarnings("serial") + public static class RandomPointFactory implements Function, Serializable { + + Dimension d; + public RandomPointFactory(Dimension d) { + this.d = d; + } + public edu.uci.ics.jung.visualization.layout.PersistentLayout.Point apply(V v) { + double x = Math.random() * d.width; + double y = Math.random() * d.height; + return new Point(x,y); + } + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayout.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayout.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/layout/PersistentLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Oct 9, 2004 + * + */ +package edu.uci.ics.jung.visualization.layout; + +import java.awt.geom.Point2D; +import java.io.IOException; +import java.io.Serializable; + +import edu.uci.ics.jung.algorithms.layout.Layout; + +/** + * interface for PersistentLayout + * Also holds a nested class Point to serialize the + * Vertex locations + * + * @author Tom Nelson + */ +public interface PersistentLayout extends Layout { + + void persist(String fileName) throws IOException; + + void restore(String fileName) throws IOException, ClassNotFoundException; + + void lock(boolean state); + + /** + * a serializable class to save locations + */ + @SuppressWarnings("serial") + static class Point implements Serializable { + public double x; + public double y; + public Point(double x, double y) { + this.x=x; + this.y=y; + } + public Point(Point2D p) { + this.x = p.getX(); + this.y = p.getY(); + } + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/MultiLayerTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/MultiLayerTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/MultiLayerTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/MultiLayerTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,28 @@ +package edu.uci.ics.jung.visualization; + +import java.awt.Shape; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; + +public interface MultiLayerTransformer extends BidirectionalTransformer, ShapeTransformer, ChangeEventSupport { + + + void setTransformer(Layer layer, MutableTransformer Function); + + MutableTransformer getTransformer(Layer layer); + + Point2D inverseTransform(Layer layer, Point2D p); + + Point2D transform(Layer layer, Point2D p); + + Shape transform(Layer layer, Shape shape); + + Shape inverseTransform(Layer layer, Shape shape); + + void setToIdentity(); + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Frameworks and mechanisms for visualizing JUNG graphs using Swing/AWT. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/AbstractPickedState.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/AbstractPickedState.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/AbstractPickedState.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/AbstractPickedState.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Apr 2, 2005 + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.event.EventListenerList; + +/** + * An abstract class to support ItemEvents for PickedState + * + * @author Tom Nelson + */ +public abstract class AbstractPickedState implements PickedState { + + protected EventListenerList listenerList = new EventListenerList(); + + public void addItemListener(ItemListener l) { + listenerList.add(ItemListener.class, l); + + } + + public void removeItemListener(ItemListener l) { + listenerList.remove(ItemListener.class, l); + } + + protected void fireItemStateChanged(ItemEvent e) { + Object[] listeners = listenerList.getListenerList(); + for ( int i = listeners.length-2; i>=0; i-=2 ) { + if ( listeners[i]==ItemListener.class ) { + ((ItemListener)listeners[i+1]).itemStateChanged(e); + } + } + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ClosestShapePickSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ClosestShapePickSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ClosestShapePickSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ClosestShapePickSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2008, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Apr 24, 2008 + * + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; + +/** + * A GraphElementAccessor that finds the closest element to + * the pick point, and returns it if it is within the element's shape. + * This is best suited to elements with convex shapes that do not overlap. + * It differs from ShapePickSupport in that it only checks + * the closest element to see whether it contains the pick point. + * Possible unexpected odd behaviors: + *

          + *
        • If the elements overlap, this mechanism may pick another element than the one that's + * "on top" (rendered last) if the pick point is closer to the center of an obscured vertex. + *
        • If element shapes are not convex, then this mechanism may return null + * even if the pick point is inside some element's shape, if the pick point is closer + * to the center of another element. + *
        + * Users who want to avoid either of these should use ShapePickSupport + * instead, which is slower but more flexible. If neither of the above conditions + * (overlapping elements or non-convex shapes) is true, then ShapePickSupport + * and this class should have the same behavior. + */ +public class ClosestShapePickSupport implements GraphElementAccessor { + + protected VisualizationServer vv; + protected float pickSize; + + /** + * Creates a ShapePickSupport for the vv + * VisualizationServer, with the specified pick footprint. + * The VisualizationServer is used to fetch the current + * Layout. + * @param vv source of the current Layout. + * @param pickSize the size of the pick footprint for line edges + */ + public ClosestShapePickSupport(VisualizationServer vv, float pickSize) + { + this.vv = vv; + this.pickSize = pickSize; + } + + /** + * Create a ShapePickSupport with the vv + * VisualizationServer and default pick footprint. + * The footprint defaults to 2. + * @param vv source of the current Layout. + */ + public ClosestShapePickSupport(VisualizationServer vv) + { + this.vv = vv; + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.GraphElementAccessor#getEdge(edu.uci.ics.jung.algorithms.layout.Layout, double, double) + */ + public E getEdge(Layout layout, double x, double y) + { + return null; + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.GraphElementAccessor#getVertex(edu.uci.ics.jung.algorithms.layout.Layout, double, double) + */ + public V getVertex(Layout layout, double x, double y) + { + // first, find the closest vertex to (x,y) + double minDistance = Double.MAX_VALUE; + V closest = null; + while(true) + { + try + { + for(V v : layout.getGraph().getVertices()) + { + Point2D p = layout.apply(v); + double dx = p.getX() - x; + double dy = p.getY() - y; + double dist = dx * dx + dy * dy; + if (dist < minDistance) + { + minDistance = dist; + closest = v; + } + } + break; + } + catch(ConcurrentModificationException cme) {} + } + + // now check to see whether (x,y) is in the shape for this vertex. + + // get the vertex shape + Shape shape = vv.getRenderContext().getVertexShapeTransformer().apply(closest); + // get the vertex location + Point2D p = layout.apply(closest); + // transform the vertex location to screen coords + p = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p); + + double ox = x - p.getX(); + double oy = y - p.getY(); + + if (shape.contains(ox, oy)) + return closest; + else + return null; + } + + /** + * @see edu.uci.ics.jung.algorithms.layout.GraphElementAccessor#getVertices(edu.uci.ics.jung.algorithms.layout.Layout, java.awt.Shape) + */ + public Collection getVertices(Layout layout, Shape rectangle) + { + // FIXME: RadiusPickSupport and ShapePickSupport are not using the same mechanism! + // talk to Tom and make sure I understand which should be used. + // in particular, there are some transformations that the latter uses; the latter is also + // doing a couple of kinds of filtering. (well, only one--just predicate-based.) + // looks to me like the VV could (should) be doing this filtering. (maybe.) + // + return null; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/LayoutLensShapePickSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/LayoutLensShapePickSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/LayoutLensShapePickSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/LayoutLensShapePickSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 11, 2005 + * + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; + +/** + * ShapePickSupport provides access to Vertices and EdgeType based on + * their actual shapes. + * + * @author Tom Nelson + * + */ +public class LayoutLensShapePickSupport extends ShapePickSupport + implements GraphElementAccessor { + + public LayoutLensShapePickSupport(VisualizationServer vv, float pickSize) { + super(vv,pickSize); + } + + public LayoutLensShapePickSupport(VisualizationServer vv) { + this(vv,2); + } + + public V getVertex(Layout layout, double x, double y) { + + V closest = null; + double minDistance = Double.MAX_VALUE; + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + + Shape shape = vv.getRenderContext().getVertexShapeTransformer().apply(v); + // get the vertex location + Point2D p = layout.apply(v); + if(p == null) continue; + // transform the vertex location to screen coords + p = vv.getRenderContext().getMultiLayerTransformer().transform(p); + AffineTransform xform = + AffineTransform.getTranslateInstance(p.getX(), p.getY()); + shape = xform.createTransformedShape(shape); + + // see if this vertex center is closest to the pick point + // among any other containing vertices + if(shape.contains(x, y)) { + + if(style == Style.LOWEST) { + // return the first match + return v; + } else if(style == Style.HIGHEST) { + // will return the last match + closest = v; + } else { + Rectangle2D bounds = shape.getBounds2D(); + double dx = bounds.getCenterX() - x; + double dy = bounds.getCenterY() - y; + double dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = v; + } + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + public Collection getVertices(Layout layout, Shape rectangle) { + Set pickedVertices = new HashSet(); + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + Point2D p = layout.apply(v); + if(p == null) continue; + + p = vv.getRenderContext().getMultiLayerTransformer().transform(p); + if(rectangle.contains(p)) { + pickedVertices.add(v); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return pickedVertices; + } + + public E getEdge(Layout layout, double x, double y) { + + Point2D ip = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, new Point2D.Double(x,y)); + x = ip.getX(); + y = ip.getY(); + + // as a Line has no area, we can't always use edgeshape.contains(point) so we + // make a small rectangular pickArea around the point and check if the + // edgeshape.intersects(pickArea) + Rectangle2D pickArea = + new Rectangle2D.Float((float)x-pickSize/2,(float)y-pickSize/2,pickSize,pickSize); + E closest = null; + double minDistance = Double.MAX_VALUE; + while(true) { + try { + for(E e : getFilteredEdges(layout)) { + + Pair pair = layout.getGraph().getEndpoints(e); + V v1 = pair.getFirst(); + V v2 = pair.getSecond(); + boolean isLoop = v1.equals(v2); + Point2D p1 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, layout.apply(v1)); + Point2D p2 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, layout.apply(v2)); + if(p1 == null || p2 == null) continue; + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + // translate the edge to the starting vertex + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + Shape edgeShape = vv.getRenderContext().getEdgeShapeTransformer().apply(e); + if(isLoop) { + // make the loops proportional to the size of the vertex + Shape s2 = vv.getRenderContext().getVertexShapeTransformer().apply(v2); + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + // move the loop so that the nadir is centered in the vertex + xform.translate(0, -edgeShape.getBounds2D().getHeight()/2); + } else { + float dx = x2 - x1; + float dy = y2 - y1; + // rotate the edge to the angle between the vertices + double theta = Math.atan2(dy,dx); + xform.rotate(theta); + // stretch the edge to span the distance between the vertices + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0f); + } + + // transform the edge to its location and dimensions + edgeShape = xform.createTransformedShape(edgeShape); + + // because of the transform, the edgeShape is now a GeneralPath + // see if this edge is the closest of any that intersect + if(edgeShape.intersects(pickArea)) { + float cx=0; + float cy=0; + float[] f = new float[6]; + PathIterator pi = new GeneralPath(edgeShape).getPathIterator(null); + if(pi.isDone()==false) { + pi.next(); + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + if(pi.isDone()==false) { + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + } + } + float dx = (float) (cx - x); + float dy = (float) (cy - y); + float dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = e; + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/MultiPickedState.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/MultiPickedState.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/MultiPickedState.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/MultiPickedState.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Mar 28, 2005 + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.event.ItemEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * Maintains the state of what has been 'picked' in the graph. + * The Sets are constructed so that their iterators + * will traverse them in the order in which they are picked. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + * + */ +public class MultiPickedState extends AbstractPickedState implements PickedState { + /** + * the 'picked' vertices + */ + protected Set picked = new LinkedHashSet(); + + public boolean pick(T v, boolean state) { + boolean prior_state = this.picked.contains(v); + if (state) { + picked.add(v); + if(prior_state == false) { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + v, ItemEvent.SELECTED)); + } + + } else { + picked.remove(v); + if(prior_state == true) { + fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED, + v, ItemEvent.DESELECTED)); + } + + } + return prior_state; + } + + public void clear() { + Collection unpicks = new ArrayList(picked); + for(T v : unpicks) { + pick(v, false); + } + picked.clear(); + + } + + public Set getPicked() { + return Collections.unmodifiableSet(picked); + } + + public boolean isPicked(T e) { + return picked.contains(e); + } + + /** + * for the ItemSelectable interface contract + */ + @SuppressWarnings("unchecked") + public T[] getSelectedObjects() { + List list = new ArrayList(picked); + return (T[])list.toArray(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Visualization mechanisms for supporting the selection of graph elements. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedInfo.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedInfo.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedInfo.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedInfo.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization.picking; + + + +/** + * An interface for classes that return information regarding whether a + * given graph element (vertex or edge) has been selected. + * + * @author danyelf + */ +public interface PickedInfo { + + public boolean isPicked(T t); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedState.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedState.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedState.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/PickedState.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + * Created on Apr 2, 2005 + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.ItemSelectable; +import java.util.Set; + +/** + * An interface for classes that keep track of the "picked" state + * of edges or vertices. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public interface PickedState extends PickedInfo, ItemSelectable { + /** + * Marks v as "picked" if b == true, + * and unmarks v as picked if b == false. + * @param v the element to be picked/unpicked + * @param b true if {@code v} is to be marked as picked, false if to be marked as unpicked + * @return the "picked" state of v prior to this call + */ + boolean pick(T v, boolean b); + + /** + * Clears the "picked" state from all elements. + */ + void clear(); + + /** + * @return all "picked" elements. + */ + Set getPicked(); + + /** + * @return true if v is currently "picked". + */ + boolean isPicked(T v); + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/RadiusPickSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/RadiusPickSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/RadiusPickSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/RadiusPickSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +/* + * Created on Mar 19, 2005 + * + */ +package edu.uci.ics.jung.visualization.picking; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.RadiusGraphElementAccessor; + + + +/** + * Simple implementation of PickSupport that returns the vertex or edge + * that is closest to the specified location. This implementation + * provides the same picking options that were available in + * previous versions of AbstractLayout. + * + * @author Tom Nelson + * @author Joshua O'Madadhain + */ +public class RadiusPickSupport + extends RadiusGraphElementAccessor implements GraphElementAccessor { + + public RadiusPickSupport() { + this(Math.sqrt(Double.MAX_VALUE - 1000)); + } + + /** + * Creates an instance with the specified maximum distance. + * @param maxDistance the farthest that a vertex can be from the selection point + * and still be 'picked' + */ + public RadiusPickSupport(double maxDistance) { + super(maxDistance); + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of maxDistance. Iterates through all + * visible vertices and checks their distance from the click. Override this + * method to provide a more efficient implementation. + */ + public V getVertex(Layout layout, double x, double y) { + return getVertex(layout, x, y, this.maxDistance); + } + + /** + * Gets the vertex nearest to the location of the (x,y) location selected, + * within a distance of maxDistance. Iterates through all + * visible vertices and checks their distance from the click. Override this + * method to provide a more efficient implementation. + * @param layout the layout instance that records the positions for all vertices + * @param x the x coordinate of the pick point + * @param y the y coordinate of the pick point + * @param maxDistance vertices whose from (x, y) is > this cannot be returned + * @return the vertex whose center is closest to the pick point (x, y) + */ + public V getVertex(Layout layout, double x, double y, double maxDistance) { + return super.getVertex(layout, x, y, maxDistance); + } + + /** + * Gets the edge nearest to the location of the (x,y) location selected. + * Calls the longer form of the call. + * @param layout the layout instance that records the positions for all vertices + * @param x the x coordinate of the pick point + * @param y the y coordinate of the pick point + * @return the vertex whose center is closest to the pick point (x, y) + */ + public E getEdge(Layout layout, double x, double y) { + return getEdge(layout, x, y, this.maxDistance); + } + + /** + * Gets the edge nearest to the location of the (x,y) location selected, + * within a distance of maxDistance, Iterates through all + * visible edges and checks their distance from the click. Override this + * method to provide a more efficient implementation. + * + * @param x the x coordinate of the pick point + * @param y the y coordinate of the pick point + * @param maxDistance vertices whose from (x, y) is > this cannot be returned + * @return Edge closest to the click. + */ + public E getEdge(Layout layout, double x, double y, double maxDistance) { + return super.getEdge(layout, x, y, maxDistance); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ShapePickSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ShapePickSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ShapePickSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ShapePickSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 11, 2005 + * + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; + +/** + * A GraphElementAccessor that returns elements whose Shape + * contains the specified pick point or region. + * + * @author Tom Nelson + * + */ +public class ShapePickSupport implements GraphElementAccessor { + + /** + * The available picking heuristics: + *

          + *
        • Style.CENTERED: returns the element whose + * center is closest to the pick point. + *
        • Style.LOWEST: returns the first such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the bottom", + * that is, the one which is rendered first.) + *
        • Style.HIGHEST: returns the last such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the top", + * that is, the one which is rendered last.) + *
        + * + */ + public static enum Style { LOWEST, CENTERED, HIGHEST }; + + protected float pickSize; + + /** + * The VisualizationServer in which the + * this instance is being used for picking. Used to + * retrieve properties such as the layout, renderer, + * vertex and edge shapes, and coordinate transformations. + */ + protected VisualizationServer vv; + + /** + * The current picking heuristic for this instance. Defaults + * to CENTERED. + */ + protected Style style = Style.CENTERED; + + /** + * Creates a ShapePickSupport for the vv + * VisualizationServer, with the specified pick footprint and + * the default pick style. + * The VisualizationServer is used to access + * properties of the current visualization (layout, renderer, + * coordinate transformations, vertex/edge shapes, etc.). + * @param vv source of the current Layout. + * @param pickSize the size of the pick footprint for line edges + */ + public ShapePickSupport(VisualizationServer vv, float pickSize) { + this.vv = vv; + this.pickSize = pickSize; + } + + /** + * Create a ShapePickSupport for the specified + * VisualizationServer with a default pick footprint. + * of size 2. + * @param vv the visualization server used for rendering + */ + public ShapePickSupport(VisualizationServer vv) { + this.vv = vv; + this.pickSize = 2; + } + + /** + * Returns the style of picking used by this instance. + * This specifies which of the elements, among those + * whose shapes contain the pick point, is returned. + * The available styles are: + *
          + *
        • Style.CENTERED: returns the element whose + * center is closest to the pick point. + *
        • Style.LOWEST: returns the first such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the bottom", + * that is, the one which is rendered first.) + *
        • Style.HIGHEST: returns the last such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the top", + * that is, the one which is rendered last.) + *
        + * + * @return the style of picking used by this instance + */ + public Style getStyle() { + return style; + } + + /** + * Specifies the style of picking to be used by this instance. + * This specifies which of the elements, among those + * whose shapes contain the pick point, will be returned. + * The available styles are: + *
          + *
        • Style.CENTERED: returns the element whose + * center is closest to the pick point. + *
        • Style.LOWEST: returns the first such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the bottom", + * that is, the one which is rendered first.) + *
        • Style.HIGHEST: returns the last such element + * encountered. (If the element collection has a consistent + * ordering, this will also be the element "on the top", + * that is, the one which is rendered last.) + *
        + * @param style the style to set + */ + public void setStyle(Style style) { + this.style = style; + } + + /** + * Returns the vertex, if any, whose shape contains (x, y). + * If (x,y) is contained in more than one vertex's shape, returns + * the vertex whose center is closest to the pick point. + * + * @param layout the layout instance that records the positions for all vertices + * @param x the x coordinate of the pick point + * @param y the y coordinate of the pick point + * @return the vertex whose shape contains (x,y), and whose center is closest to the pick point + */ + public V getVertex(Layout layout, double x, double y) { + + V closest = null; + double minDistance = Double.MAX_VALUE; + Point2D ip = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, + new Point2D.Double(x,y)); + x = ip.getX(); + y = ip.getY(); + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + + Shape shape = vv.getRenderContext().getVertexShapeTransformer().apply(v); + // get the vertex location + Point2D p = layout.apply(v); + if(p == null) continue; + // transform the vertex location to screen coords + p = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p); + + double ox = x - p.getX(); + double oy = y - p.getY(); + + if(shape.contains(ox, oy)) { + + if(style == Style.LOWEST) { + // return the first match + return v; + } else if(style == Style.HIGHEST) { + // will return the last match + closest = v; + } else { + + // return the vertex closest to the + // center of a vertex shape + Rectangle2D bounds = shape.getBounds2D(); + double dx = bounds.getCenterX() - ox; + double dy = bounds.getCenterY() - oy; + double dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = v; + } + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + /** + * Returns the vertices whose layout coordinates are contained in + * Shape. + * The shape is in screen coordinates, and the graph vertices + * are transformed to screen coordinates before they are tested + * for inclusion. + * @return the Collection of vertices whose layout + * coordinates are contained in shape. + */ + public Collection getVertices(Layout layout, Shape shape) { + Set pickedVertices = new HashSet(); + + // remove the view transform from the rectangle + shape = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, shape); + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + Point2D p = layout.apply(v); + if(p == null) continue; + + p = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p); + if(shape.contains(p)) { + pickedVertices.add(v); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return pickedVertices; + } + + /** + * Returns an edge whose shape intersects the 'pickArea' footprint of the passed + * x,y, coordinates. + * + * @param layout the context in which the location is defined + * @param x the x coordinate of the location + * @param y the y coordinate of the location + * @return an edge whose shape intersects the pick area centered on the location {@code (x,y)} + */ + public E getEdge(Layout layout, double x, double y) { + + Point2D ip = vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, new Point2D.Double(x,y)); + x = ip.getX(); + y = ip.getY(); + + // as a Line has no area, we can't always use edgeshape.contains(point) so we + // make a small rectangular pickArea around the point and check if the + // edgeshape.intersects(pickArea) + Rectangle2D pickArea = + new Rectangle2D.Float((float)x-pickSize/2,(float)y-pickSize/2,pickSize,pickSize); + E closest = null; + double minDistance = Double.MAX_VALUE; + while(true) { + try { + for(E e : getFilteredEdges(layout)) { + + Shape edgeShape = getTransformedEdgeShape(layout, e); + if (edgeShape == null) + continue; + + // because of the transform, the edgeShape is now a GeneralPath + // see if this edge is the closest of any that intersect + if(edgeShape.intersects(pickArea)) { + float cx=0; + float cy=0; + float[] f = new float[6]; + PathIterator pi = new GeneralPath(edgeShape).getPathIterator(null); + if(pi.isDone()==false) { + pi.next(); + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + if(pi.isDone()==false) { + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + } + } + float dx = (float) (cx - x); + float dy = (float) (cy - y); + float dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = e; + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + /** + * Retrieves the shape template for e and + * transforms it according to the positions of its endpoints + * in layout. + * @param layout the Layout which specifies + * e's endpoints' positions + * @param e the edge whose shape is to be returned + * @return the transformed shape + */ + private Shape getTransformedEdgeShape(Layout layout, E e) { + Pair pair = layout.getGraph().getEndpoints(e); + V v1 = pair.getFirst(); + V v2 = pair.getSecond(); + boolean isLoop = v1.equals(v2); + Point2D p1 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, layout.apply(v1)); + Point2D p2 = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, layout.apply(v2)); + if(p1 == null || p2 == null) + return null; + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + // translate the edge to the starting vertex + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + Shape edgeShape = vv.getRenderContext().getEdgeShapeTransformer().apply(e); + if(isLoop) { + // make the loops proportional to the size of the vertex + Shape s2 = vv.getRenderContext().getVertexShapeTransformer().apply(v2); + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + // move the loop so that the nadir is centered in the vertex + xform.translate(0, -edgeShape.getBounds2D().getHeight()/2); + } else { + float dx = x2 - x1; + float dy = y2 - y1; + // rotate the edge to the angle between the vertices + double theta = Math.atan2(dy,dx); + xform.rotate(theta); + // stretch the edge to span the distance between the vertices + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0f); + } + + // transform the edge to its location and dimensions + edgeShape = xform.createTransformedShape(edgeShape); + return edgeShape; + } + + protected Collection getFilteredVertices(Layout layout) { + if(verticesAreFiltered()) { + Collection unfiltered = layout.getGraph().getVertices(); + Collection filtered = new LinkedHashSet(); + for(V v : unfiltered) { + if(isVertexRendered(Context.,V>getInstance(layout.getGraph(),v))) { + filtered.add(v); + } + } + return filtered; + } else { + return layout.getGraph().getVertices(); + } + } + + protected Collection getFilteredEdges(Layout layout) { + if(edgesAreFiltered()) { + Collection unfiltered = layout.getGraph().getEdges(); + Collection filtered = new LinkedHashSet(); + for(E e : unfiltered) { + if(isEdgeRendered(Context.,E>getInstance(layout.getGraph(),e))) { + filtered.add(e); + } + } + return filtered; + } else { + return layout.getGraph().getEdges(); + } + } + + /** + * Quick test to allow optimization of getFilteredVertices(). + * @return true if there is an active vertex filtering + * mechanism for this visualization, false otherwise + */ + protected boolean verticesAreFiltered() { + Predicate,V>> vertexIncludePredicate = + vv.getRenderContext().getVertexIncludePredicate(); + return vertexIncludePredicate != null && + vertexIncludePredicate.equals(Predicates.alwaysTrue()) == false; + } + + /** + * Quick test to allow optimization of getFilteredEdges(). + * @return true if there is an active edge filtering + * mechanism for this visualization, false otherwise + */ + protected boolean edgesAreFiltered() { + Predicate,E>> edgeIncludePredicate = + vv.getRenderContext().getEdgeIncludePredicate(); + return edgeIncludePredicate != null && + edgeIncludePredicate.equals(Predicates.alwaysTrue()) == false; + } + + /** + * Returns true if this vertex in this graph is included + * in the collections of elements to be rendered, and false otherwise. + * @param context the vertex and graph to be queried + * @return true if this vertex is + * included in the collections of elements to be rendered, false + * otherwise. + */ + protected boolean isVertexRendered(Context,V> context) { + Predicate,V>> vertexIncludePredicate = + vv.getRenderContext().getVertexIncludePredicate(); + return vertexIncludePredicate == null || vertexIncludePredicate.apply(context); + } + + /** + * Returns true if this edge and its endpoints + * in this graph are all included in the collections of + * elements to be rendered, and false otherwise. + * @param context the edge and graph to be queried + * @return true if this edge and its endpoints are all + * included in the collections of elements to be rendered, false + * otherwise. + */ + protected boolean isEdgeRendered(Context,E> context) { + Predicate,V>> vertexIncludePredicate = + vv.getRenderContext().getVertexIncludePredicate(); + Predicate,E>> edgeIncludePredicate = + vv.getRenderContext().getEdgeIncludePredicate(); + Graph g = context.graph; + E e = context.element; + boolean edgeTest = edgeIncludePredicate == null || edgeIncludePredicate.apply(context); + Pair endpoints = g.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + boolean endpointsTest = vertexIncludePredicate == null || + (vertexIncludePredicate.apply(Context.,V>getInstance(g,v1)) && + vertexIncludePredicate.apply(Context.,V>getInstance(g,v2))); + return edgeTest && endpointsTest; + } + + /** + * Returns the size of the edge picking area. + * The picking area is square; the size is specified as the length of one + * side, in view coordinates. + * @return the size of the edge picking area + */ + public float getPickSize() { + return pickSize; + } + + /** + * Sets the size of the edge picking area. + * @param pickSize the length of one side of the (square) picking area, in view coordinates + */ + public void setPickSize(float pickSize) { + this.pickSize = pickSize; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ViewLensShapePickSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ViewLensShapePickSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ViewLensShapePickSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/picking/ViewLensShapePickSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * Created on Mar 11, 2005 + * + */ +package edu.uci.ics.jung.visualization.picking; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationServer; +import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator; + +/** + * ShapePickSupport provides access to Vertices and EdgeType based on + * their actual shapes. + * + * @param the vertex type + * @param the edge type + * + * @author Tom Nelson + */ +public class ViewLensShapePickSupport extends ShapePickSupport + implements GraphElementAccessor { + + public ViewLensShapePickSupport(VisualizationServer vv, float pickSize) { + super(vv, pickSize); + } + + public ViewLensShapePickSupport(VisualizationServer vv) { + this(vv, 2); + } + + public V getVertex(Layout layout, double x, double y) { + + V closest = null; + double minDistance = Double.MAX_VALUE; + Point2D ip = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(new Point2D.Double(x,y)); + x = ip.getX(); + y = ip.getY(); + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + // get the shape + Shape shape = vv.getRenderContext().getVertexShapeTransformer().apply(v); + // transform the vertex location to screen coords + Point2D p = layout.apply(v); + if(p == null) continue; + AffineTransform xform = + AffineTransform.getTranslateInstance(p.getX(), p.getY()); + shape = xform.createTransformedShape(shape); + + // use the LAYOUT transform to move the shape center without + // modifying the actual shape + Point2D lp = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p); + AffineTransform xlate = AffineTransform.getTranslateInstance( + lp.getX()-p.getX(),lp.getY()-p.getY()); + shape = xlate.createTransformedShape(shape); + // now use the VIEW transform to modify the actual shape + + shape = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.VIEW, shape); + //vv.getRenderContext().getMultiLayerTransformer().transform(shape); + + // see if this vertex center is closest to the pick point + // among any other containing vertices + if(shape.contains(x, y)) { + + if(style == Style.LOWEST) { + // return the first match + return v; + } else if(style == Style.HIGHEST) { + // will return the last match + closest = v; + } else { + Rectangle2D bounds = shape.getBounds2D(); + double dx = bounds.getCenterX() - x; + double dy = bounds.getCenterY() - y; + double dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = v; + } + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } + + public Collection getVertices(Layout layout, Shape rectangle) { + Set pickedVertices = new HashSet(); + +// remove the view transform from the rectangle + rectangle = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(rectangle); + + while(true) { + try { + for(V v : getFilteredVertices(layout)) { + Point2D p = layout.apply(v); + if(p == null) continue; + // get the shape + Shape shape = vv.getRenderContext().getVertexShapeTransformer().apply(v); + + AffineTransform xform = + AffineTransform.getTranslateInstance(p.getX(), p.getY()); + shape = xform.createTransformedShape(shape); + + shape = vv.getRenderContext().getMultiLayerTransformer().transform(shape); + Rectangle2D bounds = shape.getBounds2D(); + p.setLocation(bounds.getCenterX(),bounds.getCenterY()); + + if(rectangle.contains(p)) { + pickedVertices.add(v); + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return pickedVertices; + } + + public E getEdge(Layout layout, double x, double y) { + + Point2D ip = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(new Point2D.Double(x,y)); + x = ip.getX(); + y = ip.getY(); + + // as a Line has no area, we can't always use edgeshape.contains(point) so we + // make a small rectangular pickArea around the point and check if the + // edgeshape.intersects(pickArea) + Rectangle2D pickArea = + new Rectangle2D.Float((float)x-pickSize/2,(float)y-pickSize/2,pickSize,pickSize); + E closest = null; + double minDistance = Double.MAX_VALUE; + while(true) { + try { + for(E e : getFilteredEdges(layout)) { + + Pair pair = layout.getGraph().getEndpoints(e); + V v1 = pair.getFirst(); + V v2 = pair.getSecond(); + boolean isLoop = v1.equals(v2); + Point2D p1 = layout.apply(v1); + //vv.getRenderContext().getBasicTransformer().transform(layout.transform(v1)); + Point2D p2 = layout.apply(v2); + //vv.getRenderContext().getBasicTransformer().transform(layout.transform(v2)); + if(p1 == null || p2 == null) continue; + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + // translate the edge to the starting vertex + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + Shape edgeShape = vv.getRenderContext().getEdgeShapeTransformer().apply(e); + if(isLoop) { + // make the loops proportional to the size of the vertex + Shape s2 = vv.getRenderContext().getVertexShapeTransformer().apply(v2); + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + // move the loop so that the nadir is centered in the vertex + xform.translate(0, -edgeShape.getBounds2D().getHeight()/2); + } else { + float dx = x2 - x1; + float dy = y2 - y1; + // rotate the edge to the angle between the vertices + double theta = Math.atan2(dy,dx); + xform.rotate(theta); + // stretch the edge to span the distance between the vertices + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0f); + } + + // transform the edge to its location and dimensions + edgeShape = xform.createTransformedShape(edgeShape); + + edgeShape = vv.getRenderContext().getMultiLayerTransformer().transform(edgeShape); + + // because of the transform, the edgeShape is now a GeneralPath + // see if this edge is the closest of any that intersect + if(edgeShape.intersects(pickArea)) { + float cx=0; + float cy=0; + float[] f = new float[6]; + PathIterator pi = new GeneralPath(edgeShape).getPathIterator(null); + if(pi.isDone()==false) { + pi.next(); + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + if(pi.isDone()==false) { + pi.currentSegment(f); + cx = f[0]; + cy = f[1]; + } + } + float dx = (float) (cx - x); + float dy = (float) (cy - y); + float dist = dx * dx + dy * dy; + if (dist < minDistance) { + minDistance = dist; + closest = e; + } + } + } + break; + } catch(ConcurrentModificationException cme) {} + } + return closest; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/PivotingImageShaper.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/PivotingImageShaper.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/PivotingImageShaper.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/PivotingImageShaper.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jun 17, 2005 + */ + +package edu.uci.ics.jung.visualization; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; + + +/** + * Provides Supplier methods that, given a BufferedImage, an Image, + * or the fileName of an image, will return a java.awt.Shape that + * is the contiguous traced outline of the opaque part of the image. + * This could be used to define an image for use in a Vertex, where + * the shape used for picking and edge-arrow placement follows the + * opaque part of an image that has a transparent background. + * The methods try to detect lines in order to minimize points + * in the path + * + * @author Tom Nelson + * + * + */ +public class PivotingImageShaper { + + /** + * the number of pixels to skip while sampling the + * images edges + */ + static int sample = 1; + /** + * the first x coordinate of the shape. Used to discern + * when we are done + */ + static int firstx = 0; + + + /** + * Given an image, possibly with a transparent background, return + * the Shape of the opaque part of the image + * @param image the image whose shape is being returned + * @return the Shape + */ + public static Shape getShape(BufferedImage image) { + firstx = 0; + return leftEdge(image, new GeneralPath()); + } + + private static Point2D detectLine(Point2D p1, Point2D p2, Point2D p, + Line2D line, GeneralPath path) { + if(p2 == null) { + p2 = p; + line.setLine(p1,p2); + } + // check for line + else if(line.ptLineDistSq(p) < 1) { // its on the line + // make it p2 + p2.setLocation(p); + } else { // its not on the current line + p1.setLocation(p2); + p2.setLocation(p); + line.setLine(p1,p2); + path.lineTo((float)p1.getX(), (float)p1.getY()); + } + return p2; + } + /** + * trace the left side of the image + * @param image + * @param path + * @return + */ + private static Shape leftEdge(BufferedImage image, GeneralPath path) { + int lastj = 0; + Point2D p1 = null; + Point2D p2 = null; + Line2D line = new Line2D.Float(); + for(int i=0; i=0; j-=sample) { + if((image.getRGB(i,j) & 0xff000000) != 0) { + // this is a point I want + Point2D p = new Point2D.Float(i,j); + aPointExistsOnThisLine = true; + p2 = detectLine(p1,p2,p,line,path); + lastj = j; + break; + } + } + if(aPointExistsOnThisLine == false) { + break; + } + } + return rightEdge(image, path, lastj); + } + + /** + * trace the right side of the image + * @param image + * @param path + * @param start + * @return + */ + private static Shape rightEdge(BufferedImage image, GeneralPath path, int start) { + int lastj = 0; + Point2D p1 = path.getCurrentPoint(); + Point2D p2 = null; + Line2D line = new Line2D.Float(); + for(int i=start; i>=0; i-=sample) { + boolean aPointExistsOnThisLine = false; + + for(int j=image.getWidth()-1; j>=0; j-=sample) { + if((image.getRGB(j,i) & 0xff000000) != 0) { + // this is a point I want + Point2D p = new Point2D.Float(j,i); + aPointExistsOnThisLine = true; + p2 = detectLine(p1,p2,p,line,path); + lastj=j; + break; + } + } + if(aPointExistsOnThisLine == false) { + break; + } + } + return topEdge(image, path, lastj); + } + + /** + * trace the top of the image + * @param image + * @param path + * @param start + * @return + */ + private static Shape topEdge(BufferedImage image, GeneralPath path, int start) { + Point2D p1 = path.getCurrentPoint(); + Point2D p2 = null; + Line2D line = new Line2D.Float(); + for(int i=start; i>=firstx; i-=sample) { + boolean aPointExistsOnThisLine = false; + for(int j=0; j implements RenderContext { + + protected float arrowPlacementTolerance = 1; + protected Predicate,V>> vertexIncludePredicate = Predicates.alwaysTrue(); + protected Function vertexStrokeTransformer = + Functions.constant(new BasicStroke(1.0f)); + + protected Function vertexShapeTransformer = + Functions.constant( + new Ellipse2D.Float(-10,-10,20,20)); + + protected Function vertexLabelTransformer = Functions.constant(null); + protected Function vertexIconTransformer; + protected Function vertexFontTransformer = + Functions.constant(new Font("Helvetica", Font.PLAIN, 12)); + + protected Function vertexDrawPaintTransformer = + Functions.constant(Color.BLACK); + protected Function vertexFillPaintTransformer = + Functions.constant(Color.RED); + + protected Function edgeLabelTransformer = + Functions.constant(null); + protected Function edgeStrokeTransformer = + Functions.constant(new BasicStroke(1.0f)); + protected Function edgeArrowStrokeTransformer = + Functions.constant(new BasicStroke(1.0f)); + + protected Function,E>,Shape> edgeArrowTransformer = + new DirectionalEdgeArrowTransformer(10, 8, 4); + + protected Predicate,E>> edgeArrowPredicate = new DirectedEdgeArrowPredicate(); + protected Predicate,E>> edgeIncludePredicate = Predicates.alwaysTrue(); + protected Function edgeFontTransformer = + Functions.constant(new Font("Helvetica", Font.PLAIN, 12)); + protected Function,E>,Number> edgeLabelClosenessTransformer = + new ConstantDirectionalEdgeValueTransformer(0.5, 0.65); + protected Function edgeShapeTransformer; + protected Function edgeFillPaintTransformer = + Functions.constant(null); + protected Function edgeDrawPaintTransformer = + Functions.constant(Color.black); + protected Function arrowFillPaintTransformer = + Functions.constant(Color.black); + protected Function arrowDrawPaintTransformer = + Functions.constant(Color.black); + + protected EdgeIndexFunction parallelEdgeIndexFunction = + DefaultParallelEdgeIndexFunction.getInstance(); + + protected EdgeIndexFunction incidentEdgeIndexFunction = + IncidentEdgeIndexFunction.getInstance(); + + protected MultiLayerTransformer multiLayerTransformer = new BasicTransformer(); + + /** + * pluggable support for picking graph elements by + * finding them based on their coordinates. + */ + protected GraphElementAccessor pickSupport; + + + protected int labelOffset = LABEL_OFFSET; + + /** + * the JComponent that this Renderer will display the graph on + */ + protected JComponent screenDevice; + + protected PickedState pickedVertexState; + protected PickedState pickedEdgeState; + + /** + * The CellRendererPane is used here just as it is in JTree + * and JTable, to allow a pluggable JLabel-based renderer for + * Vertex and Edge label strings and icons. + */ + protected CellRendererPane rendererPane = new CellRendererPane(); + + /** + * A default GraphLabelRenderer - picked Vertex labels are + * blue, picked edge labels are cyan + */ + protected VertexLabelRenderer vertexLabelRenderer = + new DefaultVertexLabelRenderer(Color.blue); + + protected EdgeLabelRenderer edgeLabelRenderer = new DefaultEdgeLabelRenderer(Color.cyan); + + protected GraphicsDecorator graphicsContext; + + private EdgeShape edgeShape; + + PluggableRenderContext(Graph graph) { + this.edgeShape = new EdgeShape(graph); + this.edgeShapeTransformer = edgeShape.new QuadCurve(); + } + + /** + * @return the vertexShapeTransformer + */ + public Function getVertexShapeTransformer() { + return vertexShapeTransformer; + } + + /** + * @param vertexShapeTransformer the vertexShapeTransformer to set + */ + public void setVertexShapeTransformer( + Function vertexShapeTransformer) { + this.vertexShapeTransformer = vertexShapeTransformer; + } + + /** + * @return the vertexStrokeTransformer + */ + public Function getVertexStrokeTransformer() { + return vertexStrokeTransformer; + } + + /** + * @param vertexStrokeTransformer the vertexStrokeTransformer to set + */ + public void setVertexStrokeTransformer( + Function vertexStrokeTransformer) { + this.vertexStrokeTransformer = vertexStrokeTransformer; + } + + public static float[] getDashing() { + return dashing; + } + + public static float[] getDotting() { + return dotting; + } + + public float getArrowPlacementTolerance() { + return arrowPlacementTolerance; + } + + public void setArrowPlacementTolerance(float arrow_placement_tolerance) { + this.arrowPlacementTolerance = arrow_placement_tolerance; + } + + public Function,E>,Shape> getEdgeArrowTransformer() { + return edgeArrowTransformer; + } + + public void setEdgeArrowTransformer(Function,E>,Shape> edgeArrowTransformer) { + this.edgeArrowTransformer = edgeArrowTransformer; + } + + public Predicate,E>> getEdgeArrowPredicate() { + return edgeArrowPredicate; + } + + public void setEdgeArrowPredicate(Predicate,E>> edgeArrowPredicate) { + this.edgeArrowPredicate = edgeArrowPredicate; + } + + public Function getEdgeFontTransformer() { + return edgeFontTransformer; + } + + public void setEdgeFontTransformer(Function edgeFontTransformer) { + this.edgeFontTransformer = edgeFontTransformer; + } + + public Predicate,E>> getEdgeIncludePredicate() { + return edgeIncludePredicate; + } + + public void setEdgeIncludePredicate(Predicate,E>> edgeIncludePredicate) { + this.edgeIncludePredicate = edgeIncludePredicate; + } + + public Function,E>,Number> getEdgeLabelClosenessTransformer() { + return edgeLabelClosenessTransformer; + } + + public void setEdgeLabelClosenessTransformer( + Function,E>,Number> edgeLabelClosenessTransformer) { + this.edgeLabelClosenessTransformer = edgeLabelClosenessTransformer; + } + + public EdgeLabelRenderer getEdgeLabelRenderer() { + return edgeLabelRenderer; + } + + public void setEdgeLabelRenderer(EdgeLabelRenderer edgeLabelRenderer) { + this.edgeLabelRenderer = edgeLabelRenderer; + } + + public Function getEdgeFillPaintTransformer() { + return edgeFillPaintTransformer; + } + + public void setEdgeDrawPaintTransformer(Function edgeDrawPaintTransformer) { + this.edgeDrawPaintTransformer = edgeDrawPaintTransformer; + } + + public Function getEdgeDrawPaintTransformer() { + return edgeDrawPaintTransformer; + } + + public void setEdgeFillPaintTransformer(Function edgeFillPaintTransformer) { + this.edgeFillPaintTransformer = edgeFillPaintTransformer; + } + + public Function getEdgeShapeTransformer() { + return edgeShapeTransformer; + } + + public void setEdgeShapeTransformer(Function edgeShapeTransformer) { + this.edgeShapeTransformer = edgeShapeTransformer; + if (edgeShapeTransformer instanceof ParallelEdgeShapeTransformer) { + @SuppressWarnings("unchecked") + ParallelEdgeShapeTransformer transformer = + (ParallelEdgeShapeTransformer)edgeShapeTransformer; + if (transformer instanceof EdgeShape.Orthogonal) { + transformer.setEdgeIndexFunction(this.incidentEdgeIndexFunction); + } else { + transformer.setEdgeIndexFunction(this.parallelEdgeIndexFunction); + } + } + } + + public Function getEdgeLabelTransformer() { + return edgeLabelTransformer; + } + + public void setEdgeLabelTransformer(Function edgeLabelTransformer) { + this.edgeLabelTransformer = edgeLabelTransformer; + } + + public Function getEdgeStrokeTransformer() { + return edgeStrokeTransformer; + } + + public void setEdgeStrokeTransformer(Function edgeStrokeTransformer) { + this.edgeStrokeTransformer = edgeStrokeTransformer; + } + + public Function getEdgeArrowStrokeTransformer() { + return edgeArrowStrokeTransformer; + } + + public void setEdgeArrowStrokeTransformer(Function edgeArrowStrokeTransformer) { + this.edgeArrowStrokeTransformer = edgeArrowStrokeTransformer; + } + + public GraphicsDecorator getGraphicsContext() { + return graphicsContext; + } + + public void setGraphicsContext(GraphicsDecorator graphicsContext) { + this.graphicsContext = graphicsContext; + } + + public int getLabelOffset() { + return labelOffset; + } + + public void setLabelOffset(int labelOffset) { + this.labelOffset = labelOffset; + } + + public EdgeIndexFunction getParallelEdgeIndexFunction() { + return parallelEdgeIndexFunction; + } + + public void setParallelEdgeIndexFunction( + EdgeIndexFunction parallelEdgeIndexFunction) { + this.parallelEdgeIndexFunction = parallelEdgeIndexFunction; + // reset the edge shape Function, as the parallel edge index function + // is used by it + this.setEdgeShapeTransformer(getEdgeShapeTransformer()); + } + + public PickedState getPickedEdgeState() { + return pickedEdgeState; + } + + public void setPickedEdgeState(PickedState pickedEdgeState) { + this.pickedEdgeState = pickedEdgeState; + } + + public PickedState getPickedVertexState() { + return pickedVertexState; + } + + public void setPickedVertexState(PickedState pickedVertexState) { + this.pickedVertexState = pickedVertexState; + } + + public CellRendererPane getRendererPane() { + return rendererPane; + } + + public void setRendererPane(CellRendererPane rendererPane) { + this.rendererPane = rendererPane; + } + + public JComponent getScreenDevice() { + return screenDevice; + } + + public void setScreenDevice(JComponent screenDevice) { + this.screenDevice = screenDevice; + screenDevice.add(rendererPane); + } + + public Function getVertexFontTransformer() { + return vertexFontTransformer; + } + + public void setVertexFontTransformer(Function vertexFontTransformer) { + this.vertexFontTransformer = vertexFontTransformer; + } + + public Function getVertexIconTransformer() { + return vertexIconTransformer; + } + + public void setVertexIconTransformer(Function vertexIconTransformer) { + this.vertexIconTransformer = vertexIconTransformer; + } + + public Predicate,V>> getVertexIncludePredicate() { + return vertexIncludePredicate; + } + + public void setVertexIncludePredicate(Predicate,V>> vertexIncludePredicate) { + this.vertexIncludePredicate = vertexIncludePredicate; + } + + public VertexLabelRenderer getVertexLabelRenderer() { + return vertexLabelRenderer; + } + + public void setVertexLabelRenderer(VertexLabelRenderer vertexLabelRenderer) { + this.vertexLabelRenderer = vertexLabelRenderer; + } + + public Function getVertexFillPaintTransformer() { + return vertexFillPaintTransformer; + } + + public void setVertexFillPaintTransformer(Function vertexFillPaintTransformer) { + this.vertexFillPaintTransformer = vertexFillPaintTransformer; + } + + public Function getVertexDrawPaintTransformer() { + return vertexDrawPaintTransformer; + } + + public void setVertexDrawPaintTransformer(Function vertexDrawPaintTransformer) { + this.vertexDrawPaintTransformer = vertexDrawPaintTransformer; + } + + public Function getVertexLabelTransformer() { + return vertexLabelTransformer; + } + + public void setVertexLabelTransformer(Function vertexLabelTransformer) { + this.vertexLabelTransformer = vertexLabelTransformer; + } + + public GraphElementAccessor getPickSupport() { + return pickSupport; + } + + public void setPickSupport(GraphElementAccessor pickSupport) { + this.pickSupport = pickSupport; + } + + public MultiLayerTransformer getMultiLayerTransformer() { + return multiLayerTransformer; + } + + public void setMultiLayerTransformer(MultiLayerTransformer basicTransformer) { + this.multiLayerTransformer = basicTransformer; + } + + public Function getArrowDrawPaintTransformer() { + return arrowDrawPaintTransformer; + } + + public Function getArrowFillPaintTransformer() { + return arrowFillPaintTransformer; + } + + public void setArrowDrawPaintTransformer(Function arrowDrawPaintTransformer) { + this.arrowDrawPaintTransformer = arrowDrawPaintTransformer; + + } + + public void setArrowFillPaintTransformer(Function arrowFillPaintTransformer) { + this.arrowFillPaintTransformer = arrowFillPaintTransformer; + + } +} + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/RenderContext.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,210 @@ +package edu.uci.ics.jung.visualization; + +import java.awt.BasicStroke; +import java.awt.Font; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.Stroke; + +import javax.swing.CellRendererPane; +import javax.swing.Icon; +import javax.swing.JComponent; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.EdgeLabelRenderer; +import edu.uci.ics.jung.visualization.renderers.VertexLabelRenderer; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public interface RenderContext { + + float[] dotting = {1.0f, 3.0f}; + float[] dashing = {5.0f}; + + /** + * A stroke for a dotted line: 1 pixel width, round caps, round joins, and an + * array of {1.0f, 3.0f}. + */ + Stroke DOTTED = new BasicStroke(1.0f, + BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, dotting, 0f); + + /** + * A stroke for a dashed line: 1 pixel width, square caps, beveled joins, and an + * array of {5.0f}. + */ + Stroke DASHED = new BasicStroke(1.0f, + BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, 1.0f, dashing, 0f); + + /** + * Specifies the offset for the edge labels. + */ + int LABEL_OFFSET = 10; + + int getLabelOffset(); + + void setLabelOffset(int labelOffset); + + float getArrowPlacementTolerance(); + + void setArrowPlacementTolerance(float arrow_placement_tolerance); + + Function,E>,Shape> getEdgeArrowTransformer(); + + void setEdgeArrowTransformer(Function,E>,Shape> edgeArrowTransformer); + + Predicate,E>> getEdgeArrowPredicate() ; + + void setEdgeArrowPredicate(Predicate,E>> edgeArrowPredicate); + + Function getEdgeFontTransformer(); + + void setEdgeFontTransformer(Function edgeFontTransformer); + + Predicate,E>> getEdgeIncludePredicate(); + + void setEdgeIncludePredicate(Predicate,E>> edgeIncludePredicate); + + Function,E>,Number> getEdgeLabelClosenessTransformer(); + + void setEdgeLabelClosenessTransformer( + Function,E>,Number> edgeLabelClosenessTransformer); + + EdgeLabelRenderer getEdgeLabelRenderer(); + + void setEdgeLabelRenderer(EdgeLabelRenderer edgeLabelRenderer); + + Function getEdgeFillPaintTransformer(); + + void setEdgeFillPaintTransformer(Function edgePaintTransformer); + + Function getEdgeDrawPaintTransformer(); + + void setEdgeDrawPaintTransformer(Function edgeDrawPaintTransformer); + + Function getArrowDrawPaintTransformer(); + + void setArrowDrawPaintTransformer(Function arrowDrawPaintTransformer); + + Function getArrowFillPaintTransformer(); + + void setArrowFillPaintTransformer(Function arrowFillPaintTransformer); + + Function getEdgeShapeTransformer(); + + void setEdgeShapeTransformer(Function edgeShapeTransformer); + + Function getEdgeLabelTransformer(); + + void setEdgeLabelTransformer(Function edgeStringer); + + Function getEdgeStrokeTransformer(); + + void setEdgeStrokeTransformer(Function edgeStrokeTransformer); + + Function getEdgeArrowStrokeTransformer(); + + void setEdgeArrowStrokeTransformer(Function edgeArrowStrokeTransformer); + + GraphicsDecorator getGraphicsContext(); + + void setGraphicsContext(GraphicsDecorator graphicsContext); + + EdgeIndexFunction getParallelEdgeIndexFunction(); + + void setParallelEdgeIndexFunction( + EdgeIndexFunction parallelEdgeIndexFunction); + + PickedState getPickedEdgeState(); + + void setPickedEdgeState(PickedState pickedEdgeState); + + PickedState getPickedVertexState(); + + void setPickedVertexState(PickedState pickedVertexState); + + CellRendererPane getRendererPane(); + + void setRendererPane(CellRendererPane rendererPane); + + JComponent getScreenDevice(); + + void setScreenDevice(JComponent screenDevice); + + Function getVertexFontTransformer(); + + void setVertexFontTransformer(Function vertexFontTransformer); + + Function getVertexIconTransformer(); + + void setVertexIconTransformer(Function vertexIconTransformer); + + Predicate,V>> getVertexIncludePredicate(); + + void setVertexIncludePredicate(Predicate,V>> vertexIncludePredicate); + + VertexLabelRenderer getVertexLabelRenderer(); + + void setVertexLabelRenderer(VertexLabelRenderer vertexLabelRenderer); + + Function getVertexFillPaintTransformer(); + + void setVertexFillPaintTransformer(Function vertexFillPaintTransformer); + + Function getVertexDrawPaintTransformer(); + + void setVertexDrawPaintTransformer(Function vertexDrawPaintTransformer); + + Function getVertexShapeTransformer(); + + void setVertexShapeTransformer(Function vertexShapeTransformer); + + Function getVertexLabelTransformer(); + + void setVertexLabelTransformer(Function vertexStringer); + + Function getVertexStrokeTransformer(); + + void setVertexStrokeTransformer(Function vertexStrokeTransformer); + + class DirectedEdgeArrowPredicate + implements Predicate,E>> { + + public boolean apply(Context,E> c) { + return c.graph.getEdgeType(c.element) == EdgeType.DIRECTED; + } + + } + + class UndirectedEdgeArrowPredicate + implements Predicate,E>> { + //extends AbstractGraphPredicate { + + public boolean apply(Context,E> c) { + return c.graph.getEdgeType(c.element) == EdgeType.UNDIRECTED; + } + + } + + MultiLayerTransformer getMultiLayerTransformer(); + + void setMultiLayerTransformer(MultiLayerTransformer basicTransformer); + + /** + * @return the pickSupport + */ + GraphElementAccessor getPickSupport(); + + /** + * @param pickSupport the pickSupport to set + */ + void setPickSupport(GraphElementAccessor pickSupport); + + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeArrowRenderingSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeArrowRenderingSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeArrowRenderingSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeArrowRenderingSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.RenderContext; + +public class BasicEdgeArrowRenderingSupport implements EdgeArrowRenderingSupport { + + public AffineTransform getArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape) { + GeneralPath path = new GeneralPath(edgeShape); + float[] seg = new float[6]; + Point2D p1=null; + Point2D p2=null; + AffineTransform at = new AffineTransform(); + // when the PathIterator is done, switch to the line-subdivide + // method to get the arrowhead closer. + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + int ret = i.currentSegment(seg); + if(ret == PathIterator.SEG_MOVETO) { + p2 = new Point2D.Float(seg[0],seg[1]); + } else if(ret == PathIterator.SEG_LINETO) { + p1 = p2; + p2 = new Point2D.Float(seg[0],seg[1]); + if(vertexShape.contains(p2)) { + at = getArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); + break; + } + } + } + return at; + } + + public AffineTransform getReverseArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape) { + return getReverseArrowTransform(rc, edgeShape, vertexShape, true); + } + + public AffineTransform getReverseArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape, + boolean passedGo) { + GeneralPath path = new GeneralPath(edgeShape); + float[] seg = new float[6]; + Point2D p1=null; + Point2D p2=null; + + AffineTransform at = new AffineTransform(); + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + int ret = i.currentSegment(seg); + if(ret == PathIterator.SEG_MOVETO) { + p2 = new Point2D.Float(seg[0],seg[1]); + } else if(ret == PathIterator.SEG_LINETO) { + p1 = p2; + p2 = new Point2D.Float(seg[0],seg[1]); + if(passedGo == false && vertexShape.contains(p2)) { + passedGo = true; + } else if(passedGo==true && + vertexShape.contains(p2)==false) { + at = getReverseArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); + break; + } + } + } + return at; + } + + public AffineTransform getArrowTransform(RenderContext rc, Line2D edgeShape, Shape vertexShape) { + float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + // iterate over the line until the edge shape will place the + // arrowhead closer than 'arrowGap' to the vertex shape boundary + while((dx*dx+dy*dy) > rc.getArrowPlacementTolerance()) { + try { + edgeShape = getLastOutsideSegment(edgeShape, vertexShape); + } catch(IllegalArgumentException e) { + System.err.println(e.toString()); + return null; + } + dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + } + double atheta = Math.atan2(dx,dy)+Math.PI/2; + AffineTransform at = + AffineTransform.getTranslateInstance(edgeShape.getX1(), edgeShape.getY1()); + at.rotate(-atheta); + return at; + } + + protected AffineTransform getReverseArrowTransform(RenderContext rc, Line2D edgeShape, Shape vertexShape) { + float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + // iterate over the line until the edge shape will place the + // arrowhead closer than 'arrowGap' to the vertex shape boundary + while((dx*dx+dy*dy) > rc.getArrowPlacementTolerance()) { + try { + edgeShape = getFirstOutsideSegment(edgeShape, vertexShape); + } catch(IllegalArgumentException e) { + System.err.println(e.toString()); + return null; + } + dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + } + // calculate the angle for the arrowhead + double atheta = Math.atan2(dx,dy)-Math.PI/2; + AffineTransform at = AffineTransform.getTranslateInstance(edgeShape.getX1(),edgeShape.getY1()); + at.rotate(-atheta); + return at; + } + + /** + * Returns a line that intersects {@code shape}'s boundary. + * + * @param line line to subdivide + * @param shape shape to compare with line + * @return a line that intersects the shape boundary + * @throws IllegalArgumentException if the passed line's point2 is not inside the shape + */ + protected Line2D getLastOutsideSegment(Line2D line, Shape shape) { + if(shape.contains(line.getP2())==false) { + String errorString = + "line end point: "+line.getP2()+" is not contained in shape: "+shape.getBounds2D(); + throw new IllegalArgumentException(errorString); + //return null; + } + Line2D left = new Line2D.Double(); + Line2D right = new Line2D.Double(); + // subdivide the line until its left segment intersects + // the shape boundary + do { + subdivide(line, left, right); + line = right; + } while(shape.contains(line.getP1())==false); + // now that right is completely inside shape, + // return left, which must be partially outside + return left; + } + + /** + * Returns a line that intersects {@code shape}'s boundary. + * + * @param line line to subdivide + * @param shape shape to compare with line + * @return a line that intersects the shape boundary + * @throws IllegalArgumentException if the passed line's point1 is not inside the shape + */ + protected Line2D getFirstOutsideSegment(Line2D line, Shape shape) { + + if(shape.contains(line.getP1())==false) { + String errorString = + "line start point: "+line.getP1()+" is not contained in shape: "+shape.getBounds2D(); + throw new IllegalArgumentException(errorString); + } + Line2D left = new Line2D.Float(); + Line2D right = new Line2D.Float(); + // subdivide the line until its right side intersects the + // shape boundary + do { + subdivide(line, left, right); + line = left; + } while(shape.contains(line.getP2())==false); + // now that left is completely inside shape, + // return right, which must be partially outside + return right; + } + + /** + * divide a Line2D into 2 new Line2Ds that are returned + * in the passed left and right instances, if non-null + * @param src the line to divide + * @param left the left side, or null + * @param right the right side, or null + */ + protected void subdivide(Line2D src, + Line2D left, + Line2D right) { + double x1 = src.getX1(); + double y1 = src.getY1(); + double x2 = src.getX2(); + double y2 = src.getY2(); + + double mx = x1 + (x2-x1)/2.0; + double my = y1 + (y2-y1)/2.0; + if (left != null) { + left.setLine(x1, y1, mx, my); + } + if (right != null) { + right.setLine(mx, my, x2, y2); + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public class BasicEdgeLabelRenderer implements Renderer.EdgeLabel { + + public Component prepareRenderer(RenderContext rc, EdgeLabelRenderer graphLabelRenderer, Object value, + boolean isSelected, E edge) { + return rc.getEdgeLabelRenderer().getEdgeLabelRendererComponent(rc.getScreenDevice(), value, + rc.getEdgeFontTransformer().apply(edge), isSelected, edge); + } + + public void labelEdge(RenderContext rc, Layout layout, E e, String label) { + if(label == null || label.length() == 0) return; + + Graph graph = layout.getGraph(); + // don't draw edge if either incident vertex is not drawn + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + if (!rc.getEdgeIncludePredicate().apply(Context.,E>getInstance(graph,e))) + return; + + if (!rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v1)) || + !rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v2))) + return; + + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1); + p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2); + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + GraphicsDecorator g = rc.getGraphicsContext(); + float distX = x2 - x1; + float distY = y2 - y1; + double totalLength = Math.sqrt(distX * distX + distY * distY); + + double closeness = rc.getEdgeLabelClosenessTransformer().apply(Context.,E>getInstance(graph, e)).doubleValue(); + + int posX = (int) (x1 + (closeness) * distX); + int posY = (int) (y1 + (closeness) * distY); + + int xDisplacement = (int) (rc.getLabelOffset() * (distY / totalLength)); + int yDisplacement = (int) (rc.getLabelOffset() * (-distX / totalLength)); + + Component component = prepareRenderer(rc, rc.getEdgeLabelRenderer(), label, + rc.getPickedEdgeState().isPicked(e), e); + + Dimension d = component.getPreferredSize(); + + Shape edgeShape = rc.getEdgeShapeTransformer().apply(e); + + double parallelOffset = 1; + + parallelOffset += rc.getParallelEdgeIndexFunction().getIndex(graph, e); + + parallelOffset *= d.height; + if(edgeShape instanceof Ellipse2D) { + parallelOffset += edgeShape.getBounds().getHeight(); + parallelOffset = -parallelOffset; + } + + + AffineTransform old = g.getTransform(); + AffineTransform xform = new AffineTransform(old); + xform.translate(posX+xDisplacement, posY+yDisplacement); + double dx = x2 - x1; + double dy = y2 - y1; + if(rc.getEdgeLabelRenderer().isRotateEdgeLabels()) { + double theta = Math.atan2(dy, dx); + if(dx < 0) { + theta += Math.PI; + } + xform.rotate(theta); + } + if(dx < 0) { + parallelOffset = -parallelOffset; + } + + xform.translate(-d.width/2, -(d.height/2-parallelOffset)); + g.setTransform(xform); + g.draw(component, rc.getRendererPane(), 0, 0, d.width, d.height, true); + + g.setTransform(old); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicEdgeRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Dimension; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.ParallelEdgeShapeTransformer; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public class BasicEdgeRenderer implements Renderer.Edge { + + protected EdgeArrowRenderingSupport edgeArrowRenderingSupport = + new BasicEdgeArrowRenderingSupport(); + + public void paintEdge(RenderContext rc, Layout layout, E e) { + GraphicsDecorator g2d = rc.getGraphicsContext(); + Graph graph = layout.getGraph(); + if (!rc.getEdgeIncludePredicate().apply(Context.,E>getInstance(graph,e))) + return; + + // don't draw edge if either incident vertex is not drawn + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + if (!rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v1)) || + !rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v2))) + return; + + Stroke new_stroke = rc.getEdgeStrokeTransformer().apply(e); + Stroke old_stroke = g2d.getStroke(); + if (new_stroke != null) + g2d.setStroke(new_stroke); + + drawSimpleEdge(rc, layout, e); + + // restore paint and stroke + if (new_stroke != null) + g2d.setStroke(old_stroke); + + } + + protected Shape prepareFinalEdgeShape(RenderContext rc, Layout layout, E e, int[] coords, boolean[] loop) { + Graph graph = layout.getGraph(); + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1); + p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2); + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + coords[0] = (int)x1; + coords[1] = (int)y1; + coords[2] = (int)x2; + coords[3] = (int)y2; + + boolean isLoop = loop[0] = v1.equals(v2); + Shape s2 = rc.getVertexShapeTransformer().apply(v2); + Shape edgeShape = rc.getEdgeShapeTransformer().apply(e); + + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + if(isLoop) { + // this is a self-loop. scale it is larger than the vertex + // it decorates and translate it so that its nadir is + // at the center of the vertex. + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + xform.translate(0, -edgeShape.getBounds2D().getWidth()/2); + } else if(rc.getEdgeShapeTransformer() instanceof EdgeShape.Orthogonal) { + float dx = x2-x1; + float dy = y2-y1; + int index = 0; + if(rc.getEdgeShapeTransformer() instanceof ParallelEdgeShapeTransformer) { + @SuppressWarnings("unchecked") + EdgeIndexFunction peif = + ((ParallelEdgeShapeTransformer)rc.getEdgeShapeTransformer()) + .getEdgeIndexFunction(); + index = peif.getIndex(null, e); + index *= 20; + } + GeneralPath gp = new GeneralPath(); + gp.moveTo(0,0);// the xform will do the translation to x1,y1 + if(x1 > x2) { + if(y1 > y2) { + gp.lineTo(0, index); + gp.lineTo(dx-index, index); + gp.lineTo(dx-index, dy); + gp.lineTo(dx, dy); + } else { + gp.lineTo(0, -index); + gp.lineTo(dx-index, -index); + gp.lineTo(dx-index, dy); + gp.lineTo(dx, dy); + } + + } else { + if(y1 > y2) { + gp.lineTo(0, index); + gp.lineTo(dx+index, index); + gp.lineTo(dx+index, dy); + gp.lineTo(dx, dy); + + } else { + gp.lineTo(0, -index); + gp.lineTo(dx+index, -index); + gp.lineTo(dx+index, dy); + gp.lineTo(dx, dy); + + } + + } + + edgeShape = gp; + + } else { + // this is a normal edge. Rotate it to the angle between + // vertex endpoints, then scale it to the distance between + // the vertices + float dx = x2-x1; + float dy = y2-y1; + float thetaRadians = (float) Math.atan2(dy, dx); + xform.rotate(thetaRadians); + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0); + } + + edgeShape = xform.createTransformedShape(edgeShape); + + return edgeShape; + } + + /** + * Draws the edge e, whose endpoints are at (x1,y1) + * and (x2,y2), on the graphics context g. + * The Shape provided by the EdgeShapeFunction instance + * is scaled in the x-direction so that its width is equal to the distance between + * (x1,y1) and (x2,y2). + * @param rc the render context used for rendering the edge + * @param layout the layout instance which provides the edge's endpoints' coordinates + * @param e the edge to be drawn + */ + protected void drawSimpleEdge(RenderContext rc, Layout layout, E e) { + + int[] coords = new int[4]; + boolean[] loop = new boolean[1]; + Shape edgeShape = prepareFinalEdgeShape(rc, layout, e, coords, loop); + + int x1 = coords[0]; + int y1 = coords[1]; + int x2 = coords[2]; + int y2 = coords[3]; + boolean isLoop = loop[0]; + + GraphicsDecorator g = rc.getGraphicsContext(); + Graph graph = layout.getGraph(); + boolean edgeHit = true; + boolean arrowHit = true; + Rectangle deviceRectangle = null; + JComponent vv = rc.getScreenDevice(); + if(vv != null) { + Dimension d = vv.getSize(); + deviceRectangle = new Rectangle(0,0,d.width,d.height); + } + + MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof LensTransformer) { + vt = ((LensTransformer)vt).getDelegate(); + } + edgeHit = vt.transform(edgeShape).intersects(deviceRectangle); + + if(edgeHit == true) { + + Paint oldPaint = g.getPaint(); + + // get Paints for filling and drawing + // (filling is done first so that drawing and label use same Paint) + Paint fill_paint = rc.getEdgeFillPaintTransformer().apply(e); + if (fill_paint != null) + { + g.setPaint(fill_paint); + g.fill(edgeShape); + } + Paint draw_paint = rc.getEdgeDrawPaintTransformer().apply(e); + if (draw_paint != null) + { + g.setPaint(draw_paint); + g.draw(edgeShape); + } + + float scalex = (float)g.getTransform().getScaleX(); + float scaley = (float)g.getTransform().getScaleY(); + // see if arrows are too small to bother drawing + if(scalex < .3 || scaley < .3) return; + + if (rc.getEdgeArrowPredicate().apply(Context.,E>getInstance(graph, e))) { + + Stroke new_stroke = rc.getEdgeArrowStrokeTransformer().apply(e); + Stroke old_stroke = g.getStroke(); + if (new_stroke != null) + g.setStroke(new_stroke); + + + Shape destVertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getSecond()); + + AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2); + destVertexShape = xf.createTransformedShape(destVertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(destVertexShape).intersects(deviceRectangle); + if(arrowHit) { + + AffineTransform at = + edgeArrowRenderingSupport.getArrowTransform(rc, edgeShape, destVertexShape); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) { + Shape vertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getFirst()); + xf = AffineTransform.getTranslateInstance(x1, y1); + vertexShape = xf.createTransformedShape(vertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(vertexShape).intersects(deviceRectangle); + + if(arrowHit) { + AffineTransform at = edgeArrowRenderingSupport.getReverseArrowTransform(rc, edgeShape, vertexShape, !isLoop); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + } + // restore paint and stroke + if (new_stroke != null) + g.setStroke(old_stroke); + + } + + // restore old paint + g.setPaint(oldPaint); + } + } + + public EdgeArrowRenderingSupport getEdgeArrowRenderingSupport() { + return edgeArrowRenderingSupport; + } + + public void setEdgeArrowRenderingSupport( + EdgeArrowRenderingSupport edgeArrowRenderingSupport) { + this.edgeArrowRenderingSupport = edgeArrowRenderingSupport; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.util.ConcurrentModificationException; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.RenderContext; + +/** + * The default implementation of the Renderer used by the + * VisualizationViewer. Default Vertex and Edge Renderers + * are supplied, or the user may set custom values. The + * Vertex and Edge renderers are used in the renderVertex + * and renderEdge methods, which are called in the render + * loop of the VisualizationViewer. + * + * @author Tom Nelson + */ +public class BasicRenderer implements Renderer { + + Renderer.Vertex vertexRenderer = new BasicVertexRenderer(); + Renderer.VertexLabel vertexLabelRenderer = new BasicVertexLabelRenderer(); + Renderer.Edge edgeRenderer = new BasicEdgeRenderer(); + Renderer.EdgeLabel edgeLabelRenderer = new BasicEdgeLabelRenderer(); + + public void render(RenderContext renderContext, Layout layout) { + + // paint all the edges + try { + for(E e : layout.getGraph().getEdges()) { + + renderEdge( + renderContext, + layout, + e); + renderEdgeLabel( + renderContext, + layout, + e); + } + } catch(ConcurrentModificationException cme) { + renderContext.getScreenDevice().repaint(); + } + + // paint all the vertices + try { + for(V v : layout.getGraph().getVertices()) { + + renderVertex( + renderContext, + layout, + v); + renderVertexLabel( + renderContext, + layout, + v); + } + } catch(ConcurrentModificationException cme) { + renderContext.getScreenDevice().repaint(); + } + } + + public void renderVertex(RenderContext rc, Layout layout, V v) { + vertexRenderer.paintVertex(rc, layout, v); + } + + public void renderVertexLabel(RenderContext rc, Layout layout, V v) { + vertexLabelRenderer.labelVertex(rc, layout, v, rc.getVertexLabelTransformer().apply(v)); + } + + public void renderEdge(RenderContext rc, Layout layout, E e) { + edgeRenderer.paintEdge(rc, layout, e); + } + + public void renderEdgeLabel(RenderContext rc, Layout layout, E e) { + edgeLabelRenderer.labelEdge(rc, layout, e, rc.getEdgeLabelTransformer().apply(e)); + } + + public void setVertexRenderer(Renderer.Vertex r) { + this.vertexRenderer = r; + } + + public void setEdgeRenderer(Renderer.Edge r) { + this.edgeRenderer = r; + } + + /** + * @return the edgeLabelRenderer + */ + public Renderer.EdgeLabel getEdgeLabelRenderer() { + return edgeLabelRenderer; + } + + /** + * @param edgeLabelRenderer the edgeLabelRenderer to set + */ + public void setEdgeLabelRenderer(Renderer.EdgeLabel edgeLabelRenderer) { + this.edgeLabelRenderer = edgeLabelRenderer; + } + + /** + * @return the vertexLabelRenderer + */ + public Renderer.VertexLabel getVertexLabelRenderer() { + return vertexLabelRenderer; + } + + /** + * @param vertexLabelRenderer the vertexLabelRenderer to set + */ + public void setVertexLabelRenderer( + Renderer.VertexLabel vertexLabelRenderer) { + this.vertexLabelRenderer = vertexLabelRenderer; + } + + /** + * @return the edgeRenderer + */ + public Renderer.Edge getEdgeRenderer() { + return edgeRenderer; + } + + /** + * @return the vertexRenderer + */ + public Renderer.Vertex getVertexRenderer() { + return vertexRenderer; + } + + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; +import edu.uci.ics.jung.visualization.transform.shape.TransformingGraphics; + +public class BasicVertexLabelRenderer implements Renderer.VertexLabel { + + protected Position position = Position.SE; + private Positioner positioner = new OutsidePositioner(); + + public BasicVertexLabelRenderer() { + super(); + } + + public BasicVertexLabelRenderer(Position position) { + this.position = position; + } + + /** + * @return the position + */ + public Position getPosition() { + return position; + } + + /** + * @param position the position to set + */ + public void setPosition(Position position) { + this.position = position; + } + + public Component prepareRenderer(RenderContext rc, VertexLabelRenderer graphLabelRenderer, Object value, + boolean isSelected, V vertex) { + return rc.getVertexLabelRenderer().getVertexLabelRendererComponent(rc.getScreenDevice(), value, + rc.getVertexFontTransformer().apply(vertex), isSelected, vertex); + } + + /** + * Labels the specified vertex with the specified label. + * Uses the font specified by this instance's + * VertexFontFunction. (If the font is unspecified, the existing + * font for the graphics context is used.) If vertex label centering + * is active, the label is centered on the position of the vertex; otherwise + * the label is offset slightly. + */ + public void labelVertex(RenderContext rc, Layout layout, V v, String label) { + Graph graph = layout.getGraph(); + if (rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v)) == false) { + return; + } + Point2D pt = layout.apply(v); + pt = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, pt); + + float x = (float) pt.getX(); + float y = (float) pt.getY(); + + Component component = prepareRenderer(rc, rc.getVertexLabelRenderer(), label, + rc.getPickedVertexState().isPicked(v), v); + GraphicsDecorator g = rc.getGraphicsContext(); + Dimension d = component.getPreferredSize(); + AffineTransform xform = AffineTransform.getTranslateInstance(x, y); + + Shape shape = rc.getVertexShapeTransformer().apply(v); + shape = xform.createTransformedShape(shape); + if(rc.getGraphicsContext() instanceof TransformingGraphics) { + BidirectionalTransformer transformer = ((TransformingGraphics)rc.getGraphicsContext()).getTransformer(); + if(transformer instanceof ShapeTransformer) { + ShapeTransformer shapeTransformer = (ShapeTransformer)transformer; + shape = shapeTransformer.transform(shape); + } + } + Rectangle2D bounds = shape.getBounds2D(); + + Point p = null; + if(position == Position.AUTO) { + Dimension vvd = rc.getScreenDevice().getSize(); + if(vvd.width == 0 || vvd.height == 0) { + vvd = rc.getScreenDevice().getPreferredSize(); + } + p = getAnchorPoint(bounds, d, positioner.getPosition(x, y, vvd)); + } else { + p = getAnchorPoint(bounds, d, position); + } + g.draw(component, rc.getRendererPane(), p.x, p.y, d.width, d.height, true); + } + + protected Point getAnchorPoint(Rectangle2D vertexBounds, Dimension labelSize, Position position) { + double x; + double y; + int offset = 5; + switch(position) { + + case N: + x = vertexBounds.getCenterX()-labelSize.width/2; + y = vertexBounds.getMinY()-offset - labelSize.height; + return new Point((int)x,(int)y); + + case NE: + x = vertexBounds.getMaxX()+offset; + y = vertexBounds.getMinY()-offset-labelSize.height; + return new Point((int)x,(int)y); + + case E: + x = vertexBounds.getMaxX()+offset; + y = vertexBounds.getCenterY()-labelSize.height/2; + return new Point((int)x,(int)y); + + case SE: + x = vertexBounds.getMaxX()+offset; + y = vertexBounds.getMaxY()+offset; + return new Point((int)x,(int)y); + + case S: + x = vertexBounds.getCenterX()-labelSize.width/2; + y = vertexBounds.getMaxY()+offset; + return new Point((int)x,(int)y); + + case SW: + x = vertexBounds.getMinX()-offset-labelSize.width; + y = vertexBounds.getMaxY()+offset; + return new Point((int)x,(int)y); + + case W: + x = vertexBounds.getMinX()-offset-labelSize.width; + y = vertexBounds.getCenterY()-labelSize.height/2; + return new Point((int)x,(int)y); + + case NW: + x = vertexBounds.getMinX()-offset-labelSize.width; + y = vertexBounds.getMinY()-offset-labelSize.height; + return new Point((int)x,(int)y); + + case CNTR: + x = vertexBounds.getCenterX()-labelSize.width/2; + y = vertexBounds.getCenterY()-labelSize.height/2; + return new Point((int)x,(int)y); + + default: + return new Point(); + } + + } + public static class InsidePositioner implements Positioner { + public Position getPosition(float x, float y, Dimension d) { + int cx = d.width/2; + int cy = d.height/2; + if(x > cx && y > cy) return Position.NW; + if(x > cx && y < cy) return Position.SW; + if(x < cx && y > cy) return Position.NE; + return Position.SE; + } + } + public static class OutsidePositioner implements Positioner { + public Position getPosition(float x, float y, Dimension d) { + int cx = d.width/2; + int cy = d.height/2; + if(x > cx && y > cy) return Position.SE; + if(x > cx && y < cy) return Position.NE; + if(x < cx && y > cy) return Position.SW; + return Position.NW; + } + } + /** + * @return the positioner + */ + public Positioner getPositioner() { + return positioner; + } + + /** + * @param positioner the positioner to set + */ + public void setPositioner(Positioner positioner) { + this.positioner = positioner; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/BasicVertexRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Dimension; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import javax.swing.Icon; +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public class BasicVertexRenderer implements Renderer.Vertex { + + public void paintVertex(RenderContext rc, Layout layout, V v) { + Graph graph = layout.getGraph(); + if (rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v))) { + paintIconForVertex(rc, v, layout); + } + } + + /** + * Returns the vertex shape in view coordinates. + * @param rc the render context used for rendering the vertex + * @param v the vertex whose shape is to be returned + * @param layout the layout algorithm that provides coordinates for the vertex + * @param coords the x and y view coordinates + * @return the vertex shape in view coordinates + */ + protected Shape prepareFinalVertexShape(RenderContext rc, V v, + Layout layout, int[] coords) { + + // get the shape to be rendered + Shape shape = rc.getVertexShapeTransformer().apply(v); + Point2D p = layout.apply(v); + p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); + float x = (float)p.getX(); + float y = (float)p.getY(); + coords[0] = (int)x; + coords[1] = (int)y; + // create a transform that translates to the location of + // the vertex to be rendered + AffineTransform xform = AffineTransform.getTranslateInstance(x,y); + // transform the vertex shape with xtransform + shape = xform.createTransformedShape(shape); + return shape; + } + + /** + * Paint v's icon on g at (x,y). + * + * @param rc the render context used for rendering the vertex + * @param v the vertex to be painted + * @param layout the layout algorithm that provides coordinates for the vertex + */ + protected void paintIconForVertex(RenderContext rc, V v, Layout layout) { + GraphicsDecorator g = rc.getGraphicsContext(); + boolean vertexHit = true; + int[] coords = new int[2]; + Shape shape = prepareFinalVertexShape(rc, v, layout, coords); + vertexHit = vertexHit(rc, shape); + + if (vertexHit) { + if(rc.getVertexIconTransformer() != null) { + Icon icon = rc.getVertexIconTransformer().apply(v); + if(icon != null) { + + g.draw(icon, rc.getScreenDevice(), shape, coords[0], coords[1]); + + } else { + paintShapeForVertex(rc, v, shape); + } + } else { + paintShapeForVertex(rc, v, shape); + } + } + } + + protected boolean vertexHit(RenderContext rc, Shape s) { + JComponent vv = rc.getScreenDevice(); + Rectangle deviceRectangle = null; + if(vv != null) { + Dimension d = vv.getSize(); + deviceRectangle = new Rectangle( + 0,0, + d.width,d.height); + } + MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof MutableTransformerDecorator) { + vt = ((MutableTransformerDecorator)vt).getDelegate(); + } + return vt.transform(s).intersects(deviceRectangle); + } + + protected void paintShapeForVertex(RenderContext rc, V v, Shape shape) { + GraphicsDecorator g = rc.getGraphicsContext(); + Paint oldPaint = g.getPaint(); + Paint fillPaint = rc.getVertexFillPaintTransformer().apply(v); + if(fillPaint != null) { + g.setPaint(fillPaint); + g.fill(shape); + g.setPaint(oldPaint); + } + Paint drawPaint = rc.getVertexDrawPaintTransformer().apply(v); + if(drawPaint != null) { + g.setPaint(drawPaint); + Stroke oldStroke = g.getStroke(); + Stroke stroke = rc.getVertexStrokeTransformer().apply(v); + if(stroke != null) { + g.setStroke(stroke); + } + g.draw(shape); + g.setPaint(oldPaint); + g.setStroke(oldStroke); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingEdgeRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingEdgeRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingEdgeRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingEdgeRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,180 @@ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Dimension; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.JComponent; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.layout.LayoutChangeListener; +import edu.uci.ics.jung.visualization.layout.LayoutEvent; +import edu.uci.ics.jung.visualization.layout.LayoutEventSupport; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public class CachingEdgeRenderer extends BasicEdgeRenderer + implements ChangeListener, LayoutChangeListener { + + protected Map edgeShapeMap = new HashMap(); + protected Set dirtyEdges = new HashSet(); + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public CachingEdgeRenderer(BasicVisualizationServer vv) { + vv.getRenderContext().getMultiLayerTransformer().addChangeListener(this); + Layout layout = vv.getGraphLayout(); + if(layout instanceof LayoutEventSupport) { + ((LayoutEventSupport)layout).addLayoutChangeListener(this); + } + } + /** + * Draws the edge e, whose endpoints are at (x1,y1) + * and (x2,y2), on the graphics context g. + * The Shape provided by the EdgeShapeFunction instance + * is scaled in the x-direction so that its width is equal to the distance between + * (x1,y1) and (x2,y2). + */ + protected void drawSimpleEdge(RenderContext rc, Layout layout, E e) { + + int[] coords = new int[4]; + boolean[] loop = new boolean[1]; + + Shape edgeShape = edgeShapeMap.get(e); + if(edgeShape == null || dirtyEdges.contains(e)) { + edgeShape = prepareFinalEdgeShape(rc, layout, e, coords, loop); + edgeShapeMap.put(e, edgeShape); + dirtyEdges.remove(e); + } + + int x1 = coords[0]; + int y1 = coords[1]; + int x2 = coords[2]; + int y2 = coords[3]; + boolean isLoop = loop[0]; + + GraphicsDecorator g = rc.getGraphicsContext(); + Graph graph = layout.getGraph(); + boolean edgeHit = true; + boolean arrowHit = true; + Rectangle deviceRectangle = null; + JComponent vv = rc.getScreenDevice(); + if(vv != null) { + Dimension d = vv.getSize(); + deviceRectangle = new Rectangle(0,0,d.width,d.height); + } + MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof LensTransformer) { + vt = ((LensTransformer)vt).getDelegate(); + } + edgeHit = vt.transform(edgeShape).intersects(deviceRectangle); + + if(edgeHit == true) { + + Paint oldPaint = g.getPaint(); + + // get Paints for filling and drawing + // (filling is done first so that drawing and label use same Paint) + Paint fill_paint = rc.getEdgeFillPaintTransformer().apply(e); + if (fill_paint != null) + { + g.setPaint(fill_paint); + g.fill(edgeShape); + } + Paint draw_paint = rc.getEdgeDrawPaintTransformer().apply(e); + if (draw_paint != null) + { + g.setPaint(draw_paint); + g.draw(edgeShape); + } + + float scalex = (float)g.getTransform().getScaleX(); + float scaley = (float)g.getTransform().getScaleY(); + // see if arrows are too small to bother drawing + if(scalex < .3 || scaley < .3) return; + + if (rc.getEdgeArrowPredicate().apply(Context.,E>getInstance(graph, e))) { + + Stroke new_stroke = rc.getEdgeArrowStrokeTransformer().apply(e); + Stroke old_stroke = g.getStroke(); + if (new_stroke != null) + g.setStroke(new_stroke); + + + Shape destVertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getSecond()); + + AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2); + destVertexShape = xf.createTransformedShape(destVertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(destVertexShape).intersects(deviceRectangle); + if(arrowHit) { + + AffineTransform at = + edgeArrowRenderingSupport.getArrowTransform(rc, edgeShape, destVertexShape); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) { + Shape vertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getFirst()); + xf = AffineTransform.getTranslateInstance(x1, y1); + vertexShape = xf.createTransformedShape(vertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(vertexShape).intersects(deviceRectangle); + + if(arrowHit) { + AffineTransform at = edgeArrowRenderingSupport.getReverseArrowTransform(rc, edgeShape, vertexShape, !isLoop); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + } + // restore paint and stroke + if (new_stroke != null) + g.setStroke(old_stroke); + + } + + // restore old paint + g.setPaint(oldPaint); + } + } + +// @Override + public void stateChanged(ChangeEvent evt) { + System.err.println("got change event "+evt); + edgeShapeMap.clear(); + + } +// @Override + public void layoutChanged(LayoutEvent evt) { + V v = evt.getVertex(); + Graph graph = evt.getGraph(); + dirtyEdges.addAll(graph.getIncidentEdges(v)); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,15 @@ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Shape; +import java.util.HashMap; +import java.util.Map; + +public class CachingRenderer extends BasicRenderer { + + protected Map edgeShapeMap = new HashMap(); + + protected Map vertexShapeMap = new HashMap(); + + + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingVertexRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingVertexRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingVertexRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CachingVertexRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,77 @@ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Shape; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.Icon; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.layout.LayoutChangeListener; +import edu.uci.ics.jung.visualization.layout.LayoutEvent; +import edu.uci.ics.jung.visualization.layout.LayoutEventSupport; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +public class CachingVertexRenderer extends BasicVertexRenderer + implements ChangeListener, LayoutChangeListener { + + protected Map vertexShapeMap = new HashMap(); + + protected Set dirtyVertices = new HashSet(); + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public CachingVertexRenderer(BasicVisualizationServer vv) { + vv.getRenderContext().getMultiLayerTransformer().addChangeListener(this); + Layout layout = vv.getGraphLayout(); + if(layout instanceof LayoutEventSupport) { + ((LayoutEventSupport)layout).addLayoutChangeListener(this); + + } + } + + /** + * Paint v's icon on g at (x,y). + */ + protected void paintIconForVertex(RenderContext rc, V v, Layout layout) { + GraphicsDecorator g = rc.getGraphicsContext(); + boolean vertexHit = true; + int[] coords = new int[2]; + Shape shape = vertexShapeMap.get(v); + if(shape == null || dirtyVertices.contains(v)) { + shape = prepareFinalVertexShape(rc, v, layout, coords); + vertexShapeMap.put(v, shape); + dirtyVertices.remove(v); + } + vertexHit = vertexHit(rc, shape); + if (vertexHit) { + if(rc.getVertexIconTransformer() != null) { + Icon icon = rc.getVertexIconTransformer().apply(v); + if(icon != null) { + + g.draw(icon, rc.getScreenDevice(), shape, coords[0], coords[1]); + + } else { + paintShapeForVertex(rc, v, shape); + } + } else { + paintShapeForVertex(rc, v, shape); + } + } + } + + public void stateChanged(ChangeEvent evt) { + System.err.println("got change event "+evt); + vertexShapeMap.clear(); + + } + + public void layoutChanged(LayoutEvent evt) { + this.dirtyVertices.add(evt.getVertex()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CenterEdgeArrowRenderingSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CenterEdgeArrowRenderingSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CenterEdgeArrowRenderingSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/CenterEdgeArrowRenderingSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.RenderContext; + +public class CenterEdgeArrowRenderingSupport implements EdgeArrowRenderingSupport { + + public AffineTransform getArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape) { + GeneralPath path = new GeneralPath(edgeShape); + float[] seg = new float[6]; + Point2D p1=null; + Point2D p2=null; + AffineTransform at = new AffineTransform(); + // count the segments. + int middleSegment = 0; + int current = 0; + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + current++; + } + middleSegment = current/2; + // find the middle segment + current = 0; + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + current++; + int ret = i.currentSegment(seg); + if(ret == PathIterator.SEG_MOVETO) { + p2 = new Point2D.Float(seg[0],seg[1]); + } else if(ret == PathIterator.SEG_LINETO) { + p1 = p2; + p2 = new Point2D.Float(seg[0],seg[1]); + } + if(current > middleSegment) { // done + at = getArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); + break; + } + + } + return at; + } + + public AffineTransform getReverseArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape) { + return getReverseArrowTransform(rc, edgeShape, vertexShape, true); + } + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + * @param rc the rendering context used for rendering the arrow + * @param edgeShape the shape used to draw the edge + * @param vertexShape the shape used to draw the vertex + * @param passedGo (ignored in this implementation) + */ + public AffineTransform getReverseArrowTransform(RenderContext rc, Shape edgeShape, Shape vertexShape, + boolean passedGo) { + GeneralPath path = new GeneralPath(edgeShape); + float[] seg = new float[6]; + Point2D p1=null; + Point2D p2=null; + AffineTransform at = new AffineTransform(); + // count the segments. + int middleSegment = 0; + int current = 0; + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + current++; + } + middleSegment = current/2; + // find the middle segment + current = 0; + for(PathIterator i=path.getPathIterator(null,1); !i.isDone(); i.next()) { + current++; + int ret = i.currentSegment(seg); + if(ret == PathIterator.SEG_MOVETO) { + p2 = new Point2D.Float(seg[0],seg[1]); + } else if(ret == PathIterator.SEG_LINETO) { + p1 = p2; + p2 = new Point2D.Float(seg[0],seg[1]); + } + if(current > middleSegment) { // done + at = getReverseArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); + break; + } + } + return at; + } + + public AffineTransform getArrowTransform(RenderContext rc, Line2D edgeShape, Shape vertexShape) { + + // find the midpoint of the edgeShape line, and use it to make the transform + Line2D left = new Line2D.Float(); + Line2D right = new Line2D.Float(); + this.subdivide(edgeShape, left, right); + edgeShape = right; + float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + double atheta = Math.atan2(dx,dy)+Math.PI/2; + AffineTransform at = + AffineTransform.getTranslateInstance(edgeShape.getX1(), edgeShape.getY1()); + at.rotate(-atheta); + return at; + } + + protected AffineTransform getReverseArrowTransform(RenderContext rc, + Line2D edgeShape, Shape vertexShape) { + // find the midpoint of the edgeShape line, and use it to make the transform + Line2D left = new Line2D.Float(); + Line2D right = new Line2D.Float(); + this.subdivide(edgeShape, left, right); + edgeShape = right; + float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); + float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); + // calculate the angle for the arrowhead + double atheta = Math.atan2(dx,dy)-Math.PI/2; + AffineTransform at = AffineTransform.getTranslateInstance(edgeShape.getX1(),edgeShape.getY1()); + at.rotate(-atheta); + return at; + } + + /** + * divide a Line2D into 2 new Line2Ds that are returned + * in the passed left and right instances, if non-null + * @param src the line to divide + * @param left the left side, or null + * @param right the right side, or null + */ + protected void subdivide(Line2D src, + Line2D left, + Line2D right) { + double x1 = src.getX1(); + double y1 = src.getY1(); + double x2 = src.getX2(); + double y2 = src.getY2(); + + double mx = x1 + (x2-x1)/2.0; + double my = y1 + (y2-y1)/2.0; + if (left != null) { + left.setLine(x1, y1, mx, my); + } + if (right != null) { + right.setLine(mx, my, x2, y2); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Checkmark.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Checkmark.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Checkmark.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Checkmark.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,63 @@ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.util.Collections; + +import javax.swing.Icon; + +/** + * a simple Icon that draws a checkmark in the lower-right quadrant of its + * area. Used to draw a checkmark on Picked Vertices. + * @author Tom Nelson + */ +public class Checkmark implements Icon { + + GeneralPath path = new GeneralPath(); + AffineTransform highlight = AffineTransform.getTranslateInstance(-1,-1); + AffineTransform lowlight = AffineTransform.getTranslateInstance(1,1); + AffineTransform shadow = AffineTransform.getTranslateInstance(2,2); + Color color; + public Checkmark() { + this(Color.green); + } + public Checkmark(Color color) { + this.color = color; + path.moveTo(10,17); + path.lineTo(13,20); + path.lineTo(20,13); + } + public void paintIcon(Component c, Graphics g, int x, int y) { + Shape shape = AffineTransform.getTranslateInstance(x, y).createTransformedShape(path); + Graphics2D g2d = (Graphics2D)g; + g2d.addRenderingHints(Collections.singletonMap(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON)); + Stroke stroke = g2d.getStroke(); + g2d.setStroke(new BasicStroke(4)); + g2d.setColor(Color.darkGray); + g2d.draw(shadow.createTransformedShape(shape)); + g2d.setColor(Color.black); + g2d.draw(lowlight.createTransformedShape(shape)); + g2d.setColor(Color.white); + g2d.draw(highlight.createTransformedShape(shape)); + g2d.setColor(color); + g2d.draw(shape); + g2d.setStroke(stroke); + } + + public int getIconWidth() { + return 20; + } + + public int getIconHeight() { + return 20; + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultEdgeLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultEdgeLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultEdgeLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultEdgeLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 14, 2005 + */ + +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * DefaultEdgeLabelRenderer is similar to the cell renderers + * used by the JTable and JTree jfc classes. + * + * @author Tom Nelson + * + * + */ +@SuppressWarnings("serial") +public class DefaultEdgeLabelRenderer extends JLabel implements + EdgeLabelRenderer, Serializable { + + protected static Border noFocusBorder = new EmptyBorder(0,0,0,0); + + protected Color pickedEdgeLabelColor = Color.black; + protected boolean rotateEdgeLabels; + + public DefaultEdgeLabelRenderer(Color pickedEdgeLabelColor) { + this(pickedEdgeLabelColor, true); + } + + /** + * Creates an instance with the specified properties. + * + * @param pickedEdgeLabelColor the color to use for rendering the labels of picked edges + * @param rotateEdgeLabels whether the + */ + public DefaultEdgeLabelRenderer(Color pickedEdgeLabelColor, boolean rotateEdgeLabels) { + super(); + this.pickedEdgeLabelColor = pickedEdgeLabelColor; + this.rotateEdgeLabels = rotateEdgeLabels; + setOpaque(true); + setBorder(noFocusBorder); + } + + /** + * @return Returns the rotateEdgeLabels. + */ + public boolean isRotateEdgeLabels() { + return rotateEdgeLabels; + } + /** + * @param rotateEdgeLabels The rotateEdgeLabels to set. + */ + public void setRotateEdgeLabels(boolean rotateEdgeLabels) { + this.rotateEdgeLabels = rotateEdgeLabels; + } + /** + * Overrides JComponent.setForeground to assign + * the unselected-foreground color to the specified color. + * + * @param c set the foreground color to this value + */ + @Override + public void setForeground(Color c) { + super.setForeground(c); + } + + /** + * Overrides JComponent.setBackground to assign + * the unselected-background color to the specified color. + * + * @param c set the background color to this value + */ + @Override + public void setBackground(Color c) { + super.setBackground(c); + } + + /** + * Notification from the UIManager that the look and feel + * has changed. + * Replaces the current UI object with the latest version from the + * UIManager. + * + * @see JComponent#updateUI + */ + @Override + public void updateUI() { + super.updateUI(); + setForeground(null); + setBackground(null); + } + + /** + * + * Returns the default label renderer for an Edge + * + * @param vv the VisualizationViewer to render on + * @param value the value to assign to the label for + * Edge + * @param edge the Edge + * @return the default label renderer + */ + public Component getEdgeLabelRendererComponent(JComponent vv, Object value, + Font font, boolean isSelected, E edge) { + + super.setForeground(vv.getForeground()); + if(isSelected) setForeground(pickedEdgeLabelColor); + super.setBackground(vv.getBackground()); + + if(font != null) { + setFont(font); + } else { + setFont(vv.getFont()); + } + setIcon(null); + setBorder(noFocusBorder); + setValue(value); + return this; + } + + /* + * Implementation Note + * The following methods are overridden as a performance measure to + * prune code-paths that are often called in the case of renders + * but which we know are unnecessary. Great care should be taken + * when writing your own renderer to weigh the benefits and + * drawbacks of overriding methods like these. + */ + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public boolean isOpaque() { + Color back = getBackground(); + Component p = getParent(); + if (p != null) { + p = p.getParent(); + } + boolean colorMatch = + (back != null) && (p != null) + && back.equals(p.getBackground()) && p.isOpaque(); + return !colorMatch && super.isOpaque(); + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void validate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void revalidate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(long tm, int x, int y, int width, int height) {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(Rectangle r) { } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + // Strings get interned... + if (propertyName=="text") { + super.firePropertyChange(propertyName, oldValue, newValue); + } + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { } + + /** + * Sets the String object for the cell being rendered to + * value. + * + * @param value the string value for this cell; if value is + * null it sets the text value to an empty string + * @see JLabel#setText + * + */ + protected void setValue(Object value) { + setText((value == null) ? "" : value.toString()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultVertexLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultVertexLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultVertexLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/DefaultVertexLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 14, 2005 + */ + +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * DefaultVertexLabelRenderer is similar to the cell renderers + * used by the JTable and JTree JFC classes. + * + * @author Tom Nelson + */ +@SuppressWarnings("serial") +public class DefaultVertexLabelRenderer extends JLabel implements + VertexLabelRenderer, Serializable { + + protected static Border noFocusBorder = new EmptyBorder(0,0,0,0); + + protected Color pickedVertexLabelColor = Color.black; + + /** + * Creates a default table cell renderer. + * + * @param pickedVertexLabelColor the color to use for rendering the labels of picked vertices + */ + public DefaultVertexLabelRenderer(Color pickedVertexLabelColor) { + this.pickedVertexLabelColor = pickedVertexLabelColor; + setOpaque(true); + setBorder(noFocusBorder); + } + + /** + * Overrides JComponent.setForeground to assign + * the unselected-foreground color to the specified color. + * + * @param c set the foreground color to this value + */ + @Override + public void setForeground(Color c) { + super.setForeground(c); + } + + /** + * Overrides JComponent.setBackground to assign + * the unselected-background color to the specified color. + * + * @param c set the background color to this value + */ + @Override + public void setBackground(Color c) { + super.setBackground(c); + } + + /** + * Notification from the UIManager that the look and feel + * has changed. + * Replaces the current UI object with the latest version from the + * UIManager. + * + * @see JComponent#updateUI + */ + @Override + public void updateUI() { + super.updateUI(); + setForeground(null); + setBackground(null); + } + + /** + * + * Returns the default label renderer for a Vertex + * + * @param vv the VisualizationViewer to render on + * @param value the value to assign to the label for + * Vertex + * @param vertex the Vertex + * @return the default label renderer + */ + public Component getVertexLabelRendererComponent(JComponent vv, Object value, + Font font, boolean isSelected, V vertex) { + + super.setForeground(vv.getForeground()); + if(isSelected) setForeground(pickedVertexLabelColor); + super.setBackground(vv.getBackground()); + if(font != null) { + setFont(font); + } else { + setFont(vv.getFont()); + } + setIcon(null); + setBorder(noFocusBorder); + setValue(value); + return this; + } + + /* + * The following methods are overridden as a performance measure to + * to prune code-paths are often called in the case of renders + * but which we know are unnecessary. Great care should be taken + * when writing your own renderer to weigh the benefits and + * drawbacks of overriding methods like these. + */ + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public boolean isOpaque() { + Color back = getBackground(); + Component p = getParent(); + if (p != null) { + p = p.getParent(); + } + boolean colorMatch = (back != null) && (p != null) && + back.equals(p.getBackground()) && + p.isOpaque(); + return !colorMatch && super.isOpaque(); + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void validate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void revalidate() {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(long tm, int x, int y, int width, int height) {} + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void repaint(Rectangle r) { } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + // Strings get interned... + if (propertyName=="text") { + super.firePropertyChange(propertyName, oldValue, newValue); + } + } + + /** + * Overridden for performance reasons. + * See the Implementation Note + * for more information. + */ + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { } + + /** + * Sets the String object for the cell being rendered to + * value. + * + * @param value the string value for this cell; if value is + * null it sets the text value to an empty string + * @see JLabel#setText + * + */ + protected void setValue(Object value) { + setText((value == null) ? "" : value.toString()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeArrowRenderingSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeArrowRenderingSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeArrowRenderingSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeArrowRenderingSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,63 @@ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Line2D; + +import edu.uci.ics.jung.visualization.RenderContext; + +public interface EdgeArrowRenderingSupport { + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + * @param rc the rendering context used for rendering the arrow + * @param edgeShape the shape used to draw the edge + * @param vertexShape the shape used to draw the vertex + * @return a transform used for positioning the arrowhead for this vertex and edge + */ + AffineTransform getArrowTransform(RenderContext rc, + Shape edgeShape, Shape vertexShape); + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + * @param rc the rendering context used for rendering the arrow + * @param edgeShape the shape used to draw the edge + * @param vertexShape the shape used to draw the vertex + * @return a transform used for positioning the arrowhead for this vertex and edge + */ + AffineTransform getReverseArrowTransform( + RenderContext rc, Shape edgeShape, Shape vertexShape); + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + *

        The Loop edge is a special case because its starting point is not inside + * the vertex. The passedGo flag handles this case. + * + * @param rc the rendering context used for rendering the arrow + * @param edgeShape the shape used to draw the edge + * @param vertexShape the shape used to draw the vertex + * @param passedGo used for rendering loop edges + * @return a transform used for positioning the arrowhead for this vertex and edge + */ + AffineTransform getReverseArrowTransform( + RenderContext rc, Shape edgeShape, Shape vertexShape, + boolean passedGo); + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + * @param rc the rendering context used for rendering the arrow + * @param edgeShape the shape used to draw the edge + * @param vertexShape the shape used to draw the vertex + * @return a transform used for positioning the arrowhead for this vertex and edge + */ + AffineTransform getArrowTransform(RenderContext rc, + Line2D edgeShape, Shape vertexShape); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/EdgeLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 14, 2005 + */ + +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Component; +import java.awt.Font; + +import javax.swing.JComponent; + +/** + * @author Tom Nelson + * + * + */ +public interface EdgeLabelRenderer { + /** + * Returns the component used for drawing the label. This method is + * used to configure the renderer appropriately before drawing. + * + * @param component the component that is asking the renderer to draw + * @param value the value of the cell to be rendered; the details of how to + * render the value are up to the renderer implementation. For example, + * if {@code value} is the string "true", it could be rendered as the + * string or as a checked checkbox. + * @param font the font to use in rendering the label + * @param isSelected whether the edge is currently selected + * @param edge the edge whose label is being drawn + * @param the edge type + * @return the component used for drawing the label + */ + Component getEdgeLabelRendererComponent(JComponent component, + Object value, Font font, boolean isSelected, E edge); + + boolean isRotateEdgeLabels(); + + void setRotateEdgeLabels(boolean state); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/GradientVertexRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/GradientVertexRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/GradientVertexRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/GradientVertexRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GradientPaint; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +/** + * A renderer that will fill vertex shapes with a GradientPaint + * @author Tom Nelson + * + * @param the vertex type + * @param the edge type + */ +public class GradientVertexRenderer implements Renderer.Vertex { + + Color colorOne; + Color colorTwo; + Color pickedColorOne; + Color pickedColorTwo; + PickedState pickedState; + boolean cyclic; + + + public GradientVertexRenderer(Color colorOne, Color colorTwo, boolean cyclic) { + this.colorOne = colorOne; + this.colorTwo = colorTwo; + this.cyclic = cyclic; + } + + + public GradientVertexRenderer(Color colorOne, Color colorTwo, Color pickedColorOne, Color pickedColorTwo, PickedState pickedState, boolean cyclic) { + this.colorOne = colorOne; + this.colorTwo = colorTwo; + this.pickedColorOne = pickedColorOne; + this.pickedColorTwo = pickedColorTwo; + this.pickedState = pickedState; + this.cyclic = cyclic; + } + + + public void paintVertex(RenderContext rc, Layout layout, V v) { + Graph graph = layout.getGraph(); + if (rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v))) { + boolean vertexHit = true; + // get the shape to be rendered + Shape shape = rc.getVertexShapeTransformer().apply(v); + + Point2D p = layout.apply(v); + p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); + + float x = (float)p.getX(); + float y = (float)p.getY(); + + // create a transform that translates to the location of + // the vertex to be rendered + AffineTransform xform = AffineTransform.getTranslateInstance(x,y); + // transform the vertex shape with xtransform + shape = xform.createTransformedShape(shape); + + vertexHit = vertexHit(rc, shape); + //rc.getViewTransformer().transform(shape).intersects(deviceRectangle); + + if (vertexHit) { + paintShapeForVertex(rc, v, shape); + } + } + } + + protected boolean vertexHit(RenderContext rc, Shape s) { + JComponent vv = rc.getScreenDevice(); + Rectangle deviceRectangle = null; + if(vv != null) { + Dimension d = vv.getSize(); + deviceRectangle = new Rectangle( + 0,0, + d.width,d.height); + } + return rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(s).intersects(deviceRectangle); + } + + protected void paintShapeForVertex(RenderContext rc, V v, Shape shape) { + GraphicsDecorator g = rc.getGraphicsContext(); + Paint oldPaint = g.getPaint(); + Rectangle r = shape.getBounds(); + float y2 = (float)r.getMaxY(); + if(cyclic) { + y2 = (float)(r.getMinY()+r.getHeight()/2); + } + + Paint fillPaint = null; + if(pickedState != null && pickedState.isPicked(v)) { + fillPaint = new GradientPaint((float)r.getMinX(), (float)r.getMinY(), pickedColorOne, + (float)r.getMinX(), y2, pickedColorTwo, cyclic); + } else { + fillPaint = new GradientPaint((float)r.getMinX(), (float)r.getMinY(), colorOne, + (float)r.getMinX(), y2, colorTwo, cyclic); + } + if(fillPaint != null) { + g.setPaint(fillPaint); + g.fill(shape); + g.setPaint(oldPaint); + } + Paint drawPaint = rc.getVertexDrawPaintTransformer().apply(v); + if(drawPaint != null) { + g.setPaint(drawPaint); + } + Stroke oldStroke = g.getStroke(); + Stroke stroke = rc.getVertexStrokeTransformer().apply(v); + if(stroke != null) { + g.setStroke(stroke); + } + g.draw(shape); + g.setPaint(oldPaint); + g.setStroke(oldStroke); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Visualization mechanisms relating to rendering. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Renderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Renderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Renderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/Renderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Dimension; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.RenderContext; + +/** + * The interface for drawing vertices, edges, and their labels. + * Implementations of this class can set specific renderers for + * each element, allowing custom control of each. + */ +public interface Renderer { + + void render(RenderContext rc, Layout layout); + void renderVertex(RenderContext rc, Layout layout, V v); + void renderVertexLabel(RenderContext rc, Layout layout, V v); + void renderEdge(RenderContext rc, Layout layout, E e); + void renderEdgeLabel(RenderContext rc, Layout layout, E e); + void setVertexRenderer(Renderer.Vertex r); + void setEdgeRenderer(Renderer.Edge r); + void setVertexLabelRenderer(Renderer.VertexLabel r); + void setEdgeLabelRenderer(Renderer.EdgeLabel r); + Renderer.VertexLabel getVertexLabelRenderer(); + Renderer.Vertex getVertexRenderer(); + Renderer.Edge getEdgeRenderer(); + Renderer.EdgeLabel getEdgeLabelRenderer(); + + interface Vertex { + void paintVertex(RenderContext rc, Layout layout, V v); + @SuppressWarnings("rawtypes") + class NOOP implements Vertex { + public void paintVertex(RenderContext rc, Layout layout, Object v) {} + }; + } + + interface Edge { + void paintEdge(RenderContext rc, Layout layout, E e); + EdgeArrowRenderingSupport getEdgeArrowRenderingSupport(); + void setEdgeArrowRenderingSupport(EdgeArrowRenderingSupport edgeArrowRenderingSupport); + @SuppressWarnings("rawtypes") + class NOOP implements Edge { + public void paintEdge(RenderContext rc, Layout layout, Object e) {} + public EdgeArrowRenderingSupport getEdgeArrowRenderingSupport(){return null;} + public void setEdgeArrowRenderingSupport(EdgeArrowRenderingSupport edgeArrowRenderingSupport){} + } + } + + interface VertexLabel { + void labelVertex(RenderContext rc, Layout layout, V v, String label); + Position getPosition(); + void setPosition(Position position); + void setPositioner(Positioner positioner); + Positioner getPositioner(); + @SuppressWarnings("rawtypes") + class NOOP implements VertexLabel { + public void labelVertex(RenderContext rc, Layout layout, Object v, String label) {} + public Position getPosition() { return Position.CNTR; } + public void setPosition(Position position) {} + public Positioner getPositioner() { + return new Positioner() { + public Position getPosition(float x, float y, Dimension d) { + return Position.CNTR; + }}; + } + public void setPositioner(Positioner positioner) { + } + } + enum Position { N, NE, E, SE, S, SW, W, NW, CNTR, AUTO } + interface Positioner { + Position getPosition(float x, float y, Dimension d); + } + + } + + interface EdgeLabel { + void labelEdge(RenderContext rc, Layout layout, E e, String label); + @SuppressWarnings("rawtypes") + class NOOP implements EdgeLabel { + public void labelEdge(RenderContext rc, Layout layout, Object e, String label) {} + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/ReshapingEdgeRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/ReshapingEdgeRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/ReshapingEdgeRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/ReshapingEdgeRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Dimension; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +import javax.swing.JComponent; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; +import edu.uci.ics.jung.visualization.transform.shape.TransformingGraphics; + +/** + * uses a flatness argument to break edges into + * smaller segments. This produces a more detailed + * transformation of the edge shape + * + * @author Tom Nelson - tomnelson@dev.java.net + * + * @param the vertex type + * @param the edge type + */ +public class ReshapingEdgeRenderer extends BasicEdgeRenderer + implements Renderer.Edge { + + /** + * Draws the edge e, whose endpoints are at (x1,y1) + * and (x2,y2), on the graphics context g. + * The Shape provided by the EdgeShapeFunction instance + * is scaled in the x-direction so that its width is equal to the distance between + * (x1,y1) and (x2,y2). + */ + protected void drawSimpleEdge(RenderContext rc, Layout layout, E e) { + + TransformingGraphics g = (TransformingGraphics)rc.getGraphicsContext(); + Graph graph = layout.getGraph(); + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1); + p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2); + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + float flatness = 0; + MutableTransformer transformer = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(transformer instanceof LensTransformer) { + LensTransformer ht = (LensTransformer)transformer; + RectangularShape lensShape = ht.getLensShape(); + if(lensShape.contains(x1,y1) || lensShape.contains(x2,y2)) { + flatness = .05f; + } + } + + boolean isLoop = v1.equals(v2); + Shape s2 = rc.getVertexShapeTransformer().apply(v2); + Shape edgeShape = rc.getEdgeShapeTransformer().apply(e); + + boolean edgeHit = true; + boolean arrowHit = true; + Rectangle deviceRectangle = null; + JComponent vv = rc.getScreenDevice(); + if(vv != null) { + Dimension d = vv.getSize(); + deviceRectangle = new Rectangle(0,0,d.width,d.height); + } + + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + if(isLoop) { + // this is a self-loop. scale it is larger than the vertex + // it decorates and translate it so that its nadir is + // at the center of the vertex. + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + xform.translate(0, -edgeShape.getBounds2D().getWidth()/2); + } else { + // this is a normal edge. Rotate it to the angle between + // vertex endpoints, then scale it to the distance between + // the vertices + float dx = x2-x1; + float dy = y2-y1; + float thetaRadians = (float) Math.atan2(dy, dx); + xform.rotate(thetaRadians); + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0); + } + + edgeShape = xform.createTransformedShape(edgeShape); + + MutableTransformer vt = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW); + if(vt instanceof LensTransformer) { + vt = ((LensTransformer)vt).getDelegate(); + } + edgeHit = vt.transform(edgeShape).intersects(deviceRectangle); + + if(edgeHit == true) { + + Paint oldPaint = g.getPaint(); + + // get Paints for filling and drawing + // (filling is done first so that drawing and label use same Paint) + Paint fill_paint = rc.getEdgeFillPaintTransformer().apply(e); + if (fill_paint != null) + { + g.setPaint(fill_paint); + g.fill(edgeShape, flatness); + } + Paint draw_paint = rc.getEdgeDrawPaintTransformer().apply(e); + if (draw_paint != null) + { + g.setPaint(draw_paint); + g.draw(edgeShape, flatness); + } + + float scalex = (float)g.getTransform().getScaleX(); + float scaley = (float)g.getTransform().getScaleY(); + // see if arrows are too small to bother drawing + if(scalex < .3 || scaley < .3) return; + + if (rc.getEdgeArrowPredicate().apply(Context.,E>getInstance(graph, e))) { + + Shape destVertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getSecond()); + + AffineTransform xf = AffineTransform.getTranslateInstance(x2, y2); + destVertexShape = xf.createTransformedShape(destVertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(destVertexShape).intersects(deviceRectangle); + if(arrowHit) { + + AffineTransform at = + edgeArrowRenderingSupport.getArrowTransform(rc, new GeneralPath(edgeShape), destVertexShape); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + if (graph.getEdgeType(e) == EdgeType.UNDIRECTED) { + Shape vertexShape = + rc.getVertexShapeTransformer().apply(graph.getEndpoints(e).getFirst()); + xf = AffineTransform.getTranslateInstance(x1, y1); + vertexShape = xf.createTransformedShape(vertexShape); + + arrowHit = rc.getMultiLayerTransformer().getTransformer(Layer.VIEW).transform(vertexShape).intersects(deviceRectangle); + + if(arrowHit) { + AffineTransform at = edgeArrowRenderingSupport.getReverseArrowTransform(rc, new GeneralPath(edgeShape), vertexShape, !isLoop); + if(at == null) return; + Shape arrow = rc.getEdgeArrowTransformer().apply(Context.,E>getInstance(graph, e)); + arrow = at.createTransformedShape(arrow); + g.setPaint(rc.getArrowFillPaintTransformer().apply(e)); + g.fill(arrow); + g.setPaint(rc.getArrowDrawPaintTransformer().apply(e)); + g.draw(arrow); + } + } + } + // use existing paint for text if no draw paint specified + if (draw_paint == null) + g.setPaint(oldPaint); + + // restore old paint + g.setPaint(oldPaint); + } + } + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + */ +// public AffineTransform getArrowTransform(RenderContext rc, GeneralPath edgeShape, Shape vertexShape) { +// float[] seg = new float[6]; +// Point2D p1=null; +// Point2D p2=null; +// AffineTransform at = new AffineTransform(); +// // when the PathIterator is done, switch to the line-subdivide +// // method to get the arrowhead closer. +// for(PathIterator i=edgeShape.getPathIterator(null,1); !i.isDone(); i.next()) { +// int ret = i.currentSegment(seg); +// if(ret == PathIterator.SEG_MOVETO) { +// p2 = new Point2D.Float(seg[0],seg[1]); +// } else if(ret == PathIterator.SEG_LINETO) { +// p1 = p2; +// p2 = new Point2D.Float(seg[0],seg[1]); +// if(vertexShape.contains(p2)) { +// at = getArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); +// break; +// } +// } +// } +// return at; +// } + + /** + * Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + */ +// public AffineTransform getReverseArrowTransform(RenderContext rc, GeneralPath edgeShape, Shape vertexShape) { +// return getReverseArrowTransform(rc, edgeShape, vertexShape, true); +// } + + /** + *

        Returns a transform to position the arrowhead on this edge shape at the + * point where it intersects the passed vertex shape. + * + *

        The Loop edge is a special case because its staring point is not inside + * the vertex. The passedGo flag handles this case. + * + * @param edgeShape + * @param vertexShape + * @param passedGo - used only for Loop edges + */ +// public AffineTransform getReverseArrowTransform(RenderContext rc, GeneralPath edgeShape, Shape vertexShape, +// boolean passedGo) { +// float[] seg = new float[6]; +// Point2D p1=null; +// Point2D p2=null; +// +// AffineTransform at = new AffineTransform(); +// for(PathIterator i=edgeShape.getPathIterator(null,1); !i.isDone(); i.next()) { +// int ret = i.currentSegment(seg); +// if(ret == PathIterator.SEG_MOVETO) { +// p2 = new Point2D.Float(seg[0],seg[1]); +// } else if(ret == PathIterator.SEG_LINETO) { +// p1 = p2; +// p2 = new Point2D.Float(seg[0],seg[1]); +// if(passedGo == false && vertexShape.contains(p2)) { +// passedGo = true; +// } else if(passedGo==true && +// vertexShape.contains(p2)==false) { +// at = getReverseArrowTransform(rc, new Line2D.Float(p1,p2),vertexShape); +// break; +// } +// } +// } +// return at; +// } + + /** + * This is used for the arrow of a directed and for one of the + * arrows for non-directed edges + * Get a transform to place the arrow shape on the passed edge at the + * point where it intersects the passed shape + * @param edgeShape + * @param vertexShape + * @return + */ +// public AffineTransform getArrowTransform(RenderContext rc, Line2D edgeShape, Shape vertexShape) { +// float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); +// float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); +// // iterate over the line until the edge shape will place the +// // arrowhead closer than 'arrowGap' to the vertex shape boundary +// while((dx*dx+dy*dy) > rc.getArrowPlacementTolerance()) { +// try { +// edgeShape = getLastOutsideSegment(edgeShape, vertexShape); +// } catch(IllegalArgumentException e) { +// System.err.println(e.toString()); +// return null; +// } +// dx = (float) (edgeShape.getX1()-edgeShape.getX2()); +// dy = (float) (edgeShape.getY1()-edgeShape.getY2()); +// } +// double atheta = Math.atan2(dx,dy)+Math.PI/2; +// AffineTransform at = +// AffineTransform.getTranslateInstance(edgeShape.getX1(), edgeShape.getY1()); +// at.rotate(-atheta); +// return at; +// } + + /** + * This is used for the reverse-arrow of a non-directed edge + * get a transform to place the arrow shape on the passed edge at the + * point where it intersects the passed shape + * @param edgeShape + * @param vertexShape + * @return + */ +// protected AffineTransform getReverseArrowTransform(RenderContext rc, Line2D edgeShape, Shape vertexShape) { +// float dx = (float) (edgeShape.getX1()-edgeShape.getX2()); +// float dy = (float) (edgeShape.getY1()-edgeShape.getY2()); +// // iterate over the line until the edge shape will place the +// // arrowhead closer than 'arrowGap' to the vertex shape boundary +// while((dx*dx+dy*dy) > rc.getArrowPlacementTolerance()) { +// try { +// edgeShape = getFirstOutsideSegment(edgeShape, vertexShape); +// } catch(IllegalArgumentException e) { +// System.err.println(e.toString()); +// return null; +// } +// dx = (float) (edgeShape.getX1()-edgeShape.getX2()); +// dy = (float) (edgeShape.getY1()-edgeShape.getY2()); +// } +// // calculate the angle for the arrowhead +// double atheta = Math.atan2(dx,dy)-Math.PI/2; +// AffineTransform at = AffineTransform.getTranslateInstance(edgeShape.getX1(),edgeShape.getY1()); +// at.rotate(-atheta); +// return at; +// } + + /** + * Passed Line's point2 must be inside the passed shape or + * an IllegalArgumentException is thrown + * @param line line to subdivide + * @param shape shape to compare with line + * @return a line that intersects the shape boundary + * @throws IllegalArgumentException if the passed line's point1 is not inside the shape + */ +// protected Line2D getLastOutsideSegment(Line2D line, Shape shape) { +// if(shape.contains(line.getP2())==false) { +// String errorString = +// "line end point: "+line.getP2()+" is not contained in shape: "+shape.getBounds2D(); +// throw new IllegalArgumentException(errorString); +// //return null; +// } +// Line2D left = new Line2D.Double(); +// Line2D right = new Line2D.Double(); +// // subdivide the line until its left segment intersects +// // the shape boundary +// do { +// subdivide(line, left, right); +// line = right; +// } while(shape.contains(line.getP1())==false); +// // now that right is completely inside shape, +// // return left, which must be partially outside +// return left; +// } + + /** + * Passed Line's point1 must be inside the passed shape or + * an IllegalArgumentException is thrown + * @param line line to subdivide + * @param shape shape to compare with line + * @return a line that intersects the shape boundary + * @throws IllegalArgumentException if the passed line's point1 is not inside the shape + */ +// protected Line2D getFirstOutsideSegment(Line2D line, Shape shape) { +// +// if(shape.contains(line.getP1())==false) { +// String errorString = +// "line start point: "+line.getP1()+" is not contained in shape: "+shape.getBounds2D(); +// throw new IllegalArgumentException(errorString); +// } +// Line2D left = new Line2D.Float(); +// Line2D right = new Line2D.Float(); +// // subdivide the line until its right side intersects the +// // shape boundary +// do { +// subdivide(line, left, right); +// line = left; +// } while(shape.contains(line.getP2())==false); +// // now that left is completely inside shape, +// // return right, which must be partially outside +// return right; +// } + + /** + * divide a Line2D into 2 new Line2Ds that are returned + * in the passed left and right instances, if non-null + * @param src the line to divide + * @param left the left side, or null + * @param right the right side, or null + */ +// protected void subdivide(Line2D src, +// Line2D left, +// Line2D right) { +// double x1 = src.getX1(); +// double y1 = src.getY1(); +// double x2 = src.getX2(); +// double y2 = src.getY2(); +// +// double mx = x1 + (x2-x1)/2.0; +// double my = y1 + (y2-y1)/2.0; +// if (left != null) { +// left.setLine(x1, y1, mx, my); +// } +// if (right != null) { +// right.setLine(mx, my, x2, y2); +// } +// } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelAsShapeRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelAsShapeRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelAsShapeRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelAsShapeRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Context; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator; + +/** + * Renders Vertex Labels, but can also supply Shapes for vertices. + * This has the effect of making the vertex label the actual vertex + * shape. The user will probably want to center the vertex label + * on the vertex location. + * + * @author Tom Nelson + * + * @param the vertex type + * @param the edge type + */ +public class VertexLabelAsShapeRenderer + implements Renderer.VertexLabel, Function { + + protected Map shapes = new HashMap(); + protected RenderContext rc; + + public VertexLabelAsShapeRenderer(RenderContext rc) { + this.rc = rc; + } + + public Component prepareRenderer(RenderContext rc, VertexLabelRenderer graphLabelRenderer, Object value, + boolean isSelected, V vertex) { + return rc.getVertexLabelRenderer().getVertexLabelRendererComponent(rc.getScreenDevice(), value, + rc.getVertexFontTransformer().apply(vertex), isSelected, vertex); + } + + /** + * Labels the specified vertex with the specified label. + * Uses the font specified by this instance's + * VertexFontFunction. (If the font is unspecified, the existing + * font for the graphics context is used.) If vertex label centering + * is active, the label is centered on the position of the vertex; otherwise + * the label is offset slightly. + */ + public void labelVertex(RenderContext rc, Layout layout, V v, String label) { + Graph graph = layout.getGraph(); + if (rc.getVertexIncludePredicate().apply(Context.,V>getInstance(graph,v)) == false) { + return; + } + GraphicsDecorator g = rc.getGraphicsContext(); + Component component = prepareRenderer(rc, rc.getVertexLabelRenderer(), label, + rc.getPickedVertexState().isPicked(v), v); + Dimension d = component.getPreferredSize(); + + int h_offset = -d.width / 2; + int v_offset = -d.height / 2; + + Point2D p = layout.apply(v); + p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); + + int x = (int)p.getX(); + int y = (int)p.getY(); + + g.draw(component, rc.getRendererPane(), x+h_offset, y+v_offset, d.width, d.height, true); + + Dimension size = component.getPreferredSize(); + Rectangle bounds = new Rectangle(-size.width/2 -2, -size.height/2 -2, size.width+4, size.height); + shapes.put(v, bounds); + } + + public Shape apply(V v) { + Component component = prepareRenderer(rc, rc.getVertexLabelRenderer(), rc.getVertexLabelTransformer().apply(v), + rc.getPickedVertexState().isPicked(v), v); + Dimension size = component.getPreferredSize(); + Rectangle bounds = new Rectangle(-size.width/2 -2, -size.height/2 -2, size.width+4, size.height); + return bounds; +// Shape shape = shapes.get(v); +// if(shape == null) { +// return new Rectangle(-20,-20,40,40); +// } +// else return shape; + } + + public Renderer.VertexLabel.Position getPosition() { + return Renderer.VertexLabel.Position.CNTR; + } + + public Renderer.VertexLabel.Positioner getPositioner() { + return new Positioner() { + public Renderer.VertexLabel.Position getPosition(float x, float y, Dimension d) { + return Renderer.VertexLabel.Position.CNTR; + }}; + } + + public void setPosition(Renderer.VertexLabel.Position position) { + // noop + } + + public void setPositioner(Renderer.VertexLabel.Positioner positioner) { + //noop + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelRenderer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelRenderer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelRenderer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/renderers/VertexLabelRenderer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 14, 2005 + */ + +package edu.uci.ics.jung.visualization.renderers; + +import java.awt.Component; +import java.awt.Font; + +import javax.swing.JComponent; + +/** + * @author Tom Nelson + * + * + */ +public interface VertexLabelRenderer { + /** + * Returns the component used for drawing the label. This method is + * used to configure the renderer appropriately before drawing. + * + * @param vv the component that is asking the renderer to draw + * @param value the value of the cell to be rendered; the details of how to + * render the value are up to the renderer implementation. For example, + * if {@code value} is the string "true", it could be rendered as the + * string or as a checked checkbox. + * @param font the font to use in rendering the label + * @param isSelected whether the vertex is currently selected + * @param vertex the edge whose label is being drawn + * @param the vertex type + * @return the component used for drawing the label + */ + Component getVertexLabelRendererComponent(JComponent vv, Object value, + Font font, boolean isSelected, V vertex); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/AggregateGraph.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/AggregateGraph.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/AggregateGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/AggregateGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,271 @@ +package edu.uci.ics.jung.visualization.spatial; + +import java.util.Collection; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; + +public class AggregateGraph implements Graph { + + +// @Override + public boolean addEdge(E e, V v1, V v2) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public V getDest(E directedEdge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Pair getEndpoints(E edge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection getInEdges(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public V getOpposite(V vertex, E edge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection getOutEdges(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getPredecessorCount(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public Collection getPredecessors(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public V getSource(E directedEdge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getSuccessorCount(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public Collection getSuccessors(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int inDegree(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public boolean isDest(V vertex, E edge) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean isPredecessor(V v1, V v2) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean isSource(V vertex, E edge) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean isSuccessor(V v1, V v2) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public int outDegree(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public boolean addEdge(E edge, Collection vertices) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean addEdge(E edge, Collection vertices, + EdgeType edgeType) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean addVertex(V vertex) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean containsEdge(E edge) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean containsVertex(V vertex) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public int degree(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public E findEdge(V v1, V v2) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection findEdgeSet(V v1, V v2) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public EdgeType getDefaultEdgeType() { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getEdgeCount() { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public int getEdgeCount(EdgeType edgeType) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public EdgeType getEdgeType(E edge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection getEdges() { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection getEdges(EdgeType edgeType) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getIncidentCount(E edge) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public Collection getIncidentEdges(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public Collection getIncidentVertices(E edge) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getNeighborCount(V vertex) { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public Collection getNeighbors(V vertex) { + // TODO Auto-generated method stub + return null; + } + +// @Override + public int getVertexCount() { + // TODO Auto-generated method stub + return 0; + } + +// @Override + public Collection getVertices() { + // TODO Auto-generated method stub + return null; + } + +// @Override + public boolean isIncident(V vertex, E edge) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean isNeighbor(V v1, V v2) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean removeEdge(E edge) { + // TODO Auto-generated method stub + return false; + } + +// @Override + public boolean removeVertex(V vertex) { + // TODO Auto-generated method stub + return false; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingGraph.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingGraph.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingGraph.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingGraph.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,315 @@ +package edu.uci.ics.jung.visualization.spatial; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; +import edu.uci.ics.jung.graph.util.EdgeType; +import edu.uci.ics.jung.graph.util.Pair; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.decorators.EdgeShape; +import edu.uci.ics.jung.visualization.decorators.ParallelEdgeShapeTransformer; + +/** + * maintains caches of vertices and edges that will be the subset of the + * delegate graph's elements that are contained in some Rectangle. + * + * @author tanelso + * + * @param the vertex type + * @param the edge type + */ +public class FastRenderingGraph implements Graph { + + protected Graph graph; + protected Set vertices = new HashSet(); + protected Set edges = new HashSet(); + protected boolean dirty; + protected Set bounds; + protected RenderContext rc; + protected BasicVisualizationServer vv; + protected Layout layout; + + public FastRenderingGraph(Graph graph, Set bounds, BasicVisualizationServer vv) { + this.graph = graph; + this.bounds = bounds; + this.vv = vv; + this.rc = vv.getRenderContext(); + } + + private void cleanUp() { + vertices.clear(); + edges.clear(); + for(V v : graph.getVertices()) { + checkVertex(v); + } + for(E e : graph.getEdges()) { + checkEdge(e); + } + } + + private void checkVertex(V v) { + // get the shape to be rendered + Shape shape = rc.getVertexShapeTransformer().apply(v); + Point2D p = layout.apply(v); + p = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p); + float x = (float)p.getX(); + float y = (float)p.getY(); + // create a transform that translates to the location of + // the vertex to be rendered + AffineTransform xform = AffineTransform.getTranslateInstance(x,y); + // transform the vertex shape with xtransform + shape = xform.createTransformedShape(shape); + for(Rectangle2D r : bounds) { + if(shape.intersects(r)) { + vertices.add(v); + } + } + } + + private void checkEdge(E e) { + Pair endpoints = graph.getEndpoints(e); + V v1 = endpoints.getFirst(); + V v2 = endpoints.getSecond(); + + Point2D p1 = layout.apply(v1); + Point2D p2 = layout.apply(v2); + p1 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p1); + p2 = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, p2); + float x1 = (float) p1.getX(); + float y1 = (float) p1.getY(); + float x2 = (float) p2.getX(); + float y2 = (float) p2.getY(); + + boolean isLoop = v1.equals(v2); + Shape s2 = rc.getVertexShapeTransformer().apply(v2); + Shape edgeShape = rc.getEdgeShapeTransformer().apply(e); + + AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1); + + if(isLoop) { + // this is a self-loop. scale it is larger than the vertex + // it decorates and translate it so that its nadir is + // at the center of the vertex. + Rectangle2D s2Bounds = s2.getBounds2D(); + xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight()); + xform.translate(0, -edgeShape.getBounds2D().getWidth()/2); + } else if(rc.getEdgeShapeTransformer() instanceof EdgeShape.Orthogonal) { + float dx = x2-x1; + float dy = y2-y1; + int index = 0; + if(rc.getEdgeShapeTransformer() instanceof ParallelEdgeShapeTransformer) { + @SuppressWarnings("unchecked") + EdgeIndexFunction peif = + ((ParallelEdgeShapeTransformer)rc.getEdgeShapeTransformer()) + .getEdgeIndexFunction(); + index = peif.getIndex(null, e); + index *= 20; + } + GeneralPath gp = new GeneralPath(); + gp.moveTo(0,0);// the xform will do the translation to x1,y1 + if(x1 > x2) { + if(y1 > y2) { + gp.lineTo(0, index); + gp.lineTo(dx-index, index); + gp.lineTo(dx-index, dy); + gp.lineTo(dx, dy); + } else { + gp.lineTo(0, -index); + gp.lineTo(dx-index, -index); + gp.lineTo(dx-index, dy); + gp.lineTo(dx, dy); + } + + } else { + if(y1 > y2) { + gp.lineTo(0, index); + gp.lineTo(dx+index, index); + gp.lineTo(dx+index, dy); + gp.lineTo(dx, dy); + + } else { + gp.lineTo(0, -index); + gp.lineTo(dx+index, -index); + gp.lineTo(dx+index, dy); + gp.lineTo(dx, dy); + + } + + } + + edgeShape = gp; + + } else { + // this is a normal edge. Rotate it to the angle between + // vertex endpoints, then scale it to the distance between + // the vertices + float dx = x2-x1; + float dy = y2-y1; + float thetaRadians = (float) Math.atan2(dy, dx); + xform.rotate(thetaRadians); + float dist = (float) Math.sqrt(dx*dx + dy*dy); + xform.scale(dist, 1.0); + } + + edgeShape = xform.createTransformedShape(edgeShape); + for(Rectangle2D r : bounds) { + if(edgeShape.intersects(r)) { + edges.add(e); + } + } + } + + public Set getBounds() { + return bounds; + } + + public void setBounds(Set bounds) { + this.bounds = bounds; + } + + public boolean addEdge(E edge, Collection vertices, + EdgeType edgeType) { + return graph.addEdge(edge, vertices, edgeType); + } + public boolean addEdge(E edge, Collection vertices) { + return graph.addEdge(edge, vertices); + } + public boolean addEdge(E e, V v1, V v2, EdgeType edgeType) { + return graph.addEdge(e, v1, v2, edgeType); + } + public boolean addEdge(E e, V v1, V v2) { + return graph.addEdge(e, v1, v2); + } + public boolean addVertex(V vertex) { + return graph.addVertex(vertex); + } + public boolean containsEdge(E edge) { + return graph.containsEdge(edge); + } + public boolean containsVertex(V vertex) { + return graph.containsVertex(vertex); + } + public int degree(V vertex) { + return graph.degree(vertex); + } + public E findEdge(V v1, V v2) { + return graph.findEdge(v1, v2); + } + public Collection findEdgeSet(V v1, V v2) { + return graph.findEdgeSet(v1, v2); + } + public EdgeType getDefaultEdgeType() { + return graph.getDefaultEdgeType(); + } + public V getDest(E directedEdge) { + return graph.getDest(directedEdge); + } + public int getEdgeCount() { + return graph.getEdgeCount(); + } + public int getEdgeCount(EdgeType edgeType) { + return graph.getEdgeCount(edgeType); + } + public Collection getEdges() { + if(dirty) { + cleanUp(); + } + return edges; + } + public Collection getEdges(EdgeType edgeType) { + return graph.getEdges(edgeType); + } + public EdgeType getEdgeType(E edge) { + return graph.getEdgeType(edge); + } + public Pair getEndpoints(E edge) { + return graph.getEndpoints(edge); + } + public int getIncidentCount(E edge) { + return graph.getIncidentCount(edge); + } + public Collection getIncidentEdges(V vertex) { + return graph.getIncidentEdges(vertex); + } + public Collection getIncidentVertices(E edge) { + return graph.getIncidentVertices(edge); + } + public Collection getInEdges(V vertex) { + return graph.getInEdges(vertex); + } + public int getNeighborCount(V vertex) { + return graph.getNeighborCount(vertex); + } + public Collection getNeighbors(V vertex) { + return graph.getNeighbors(vertex); + } + public V getOpposite(V vertex, E edge) { + return graph.getOpposite(vertex, edge); + } + public Collection getOutEdges(V vertex) { + return graph.getOutEdges(vertex); + } + public int getPredecessorCount(V vertex) { + return graph.getPredecessorCount(vertex); + } + public Collection getPredecessors(V vertex) { + return graph.getPredecessors(vertex); + } + public V getSource(E directedEdge) { + return graph.getSource(directedEdge); + } + public int getSuccessorCount(V vertex) { + return graph.getSuccessorCount(vertex); + } + public Collection getSuccessors(V vertex) { + return graph.getSuccessors(vertex); + } + public int getVertexCount() { + return graph.getVertexCount(); + } + public Collection getVertices() { + if(dirty) cleanUp(); + return vertices; + } + public int inDegree(V vertex) { + return graph.inDegree(vertex); + } + public boolean isDest(V vertex, E edge) { + return graph.isDest(vertex, edge); + } + public boolean isIncident(V vertex, E edge) { + return graph.isIncident(vertex, edge); + } + public boolean isNeighbor(V v1, V v2) { + return graph.isNeighbor(v1, v2); + } + public boolean isPredecessor(V v1, V v2) { + return graph.isPredecessor(v1, v2); + } + public boolean isSource(V vertex, E edge) { + return graph.isSource(vertex, edge); + } + public boolean isSuccessor(V v1, V v2) { + return graph.isSuccessor(v1, v2); + } + public int outDegree(V vertex) { + return graph.outDegree(vertex); + } + public boolean removeEdge(E edge) { + return graph.removeEdge(edge); + } + public boolean removeVertex(V vertex) { + return graph.removeVertex(vertex); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingLayout.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingLayout.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingLayout.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/spatial/FastRenderingLayout.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,74 @@ +package edu.uci.ics.jung.visualization.spatial; + +import java.awt.Dimension; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Graph; + +/** + * break into several rectangular areas, each of which will have a reference Graph + * @author tanelso + * + * @param the vertex type + * @param the edge type + */ +public class FastRenderingLayout implements Layout { + + protected Layout layout; + protected Graph graph; + + protected Rectangle2D[][] grid; + + public FastRenderingLayout(Layout layout) { + this.layout = layout; + } + + public Graph getGraph() { + return layout.getGraph(); + } + + public Dimension getSize() { + return layout.getSize(); + } + + public void initialize() { + layout.initialize(); + } + + public boolean isLocked(V v) { + return layout.isLocked(v); + } + + public void lock(V v, boolean state) { + layout.lock(v, state); + } + + public void reset() { + layout.reset(); + } + + public void setGraph(Graph graph) { +// layout.setGraph(new FastRenderingGraph(graph)); + } + + public void setInitializer(Function initializer) { + layout.setInitializer(initializer); + } + + public void setLocation(V v, Point2D location) { + layout.setLocation(v, location); + } + + public void setSize(Dimension d) { + layout.setSize(d); + } + + public Point2D apply(V arg0) { + return layout.apply(arg0); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/GraphCollapser.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/GraphCollapser.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/GraphCollapser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/GraphCollapser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.subLayout; + +import com.google.common.base.Preconditions; + +import java.util.Collection; +import java.util.logging.Logger; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.Pair; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class GraphCollapser { + + private static final Logger logger = Logger.getLogger(GraphCollapser.class.getClass().getName()); + private Graph originalGraph; + + public GraphCollapser(Graph originalGraph) { + this.originalGraph = originalGraph; + } + + Graph createGraph() throws InstantiationException, IllegalAccessException { + return (Graph)originalGraph.getClass().newInstance(); + } + + public Graph collapse(Graph inGraph, Graph clusterGraph) { + + if(clusterGraph.getVertexCount() < 2) return inGraph; + + Graph graph = inGraph; + try { + graph = createGraph(); + } catch(Exception ex) { + ex.printStackTrace(); + } + Collection cluster = clusterGraph.getVertices(); + + // add all vertices in the delegate, unless the vertex is in the + // cluster. + for(Object v : inGraph.getVertices()) { + if(cluster.contains(v) == false) { + graph.addVertex(v); + } + } + // add the clusterGraph as a vertex + graph.addVertex(clusterGraph); + + //add all edges from the inGraph, unless both endpoints of + // the edge are in the cluster + for(Object e : (Collection)inGraph.getEdges()) { + Pair endpoints = inGraph.getEndpoints(e); + // don't add edges whose endpoints are both in the cluster + if(cluster.containsAll(endpoints) == false) { + + if(cluster.contains(endpoints.getFirst())) { + graph.addEdge(e, clusterGraph, endpoints.getSecond(), inGraph.getEdgeType(e)); + + } else if(cluster.contains(endpoints.getSecond())) { + graph.addEdge(e, endpoints.getFirst(), clusterGraph, inGraph.getEdgeType(e)); + + } else { + graph.addEdge(e,endpoints.getFirst(), endpoints.getSecond(), inGraph.getEdgeType(e)); + } + } + } + return graph; + } + + public Graph expand(Graph inGraph, Graph clusterGraph) { + Graph graph = inGraph; + try { + graph = createGraph(); + } catch(Exception ex) { + ex.printStackTrace(); + } + Collection cluster = clusterGraph.getVertices(); + logger.fine("cluster to expand is "+cluster); + + // put all clusterGraph vertices and edges into the new Graph + for(Object v : cluster) { + graph.addVertex(v); + for(Object edge : clusterGraph.getIncidentEdges(v)) { + Pair endpoints = clusterGraph.getEndpoints(edge); + graph.addEdge(edge, endpoints.getFirst(), endpoints.getSecond(), clusterGraph.getEdgeType(edge)); + } + } + // add all the vertices from the current graph except for + // the cluster we are expanding + for(Object v : inGraph.getVertices()) { + if(v.equals(clusterGraph) == false) { + graph.addVertex(v); + } + } + + // now that all vertices have been added, add the edges, + // ensuring that no edge contains a vertex that has not + // already been added + for(Object v : inGraph.getVertices()) { + if(v.equals(clusterGraph) == false) { + for(Object edge : inGraph.getIncidentEdges(v)) { + Pair endpoints = inGraph.getEndpoints(edge); + Object v1 = endpoints.getFirst(); + Object v2 = endpoints.getSecond(); + if(cluster.containsAll(endpoints) == false) { + if(clusterGraph.equals(v1)) { + // i need a new v1 + Object originalV1 = originalGraph.getEndpoints(edge).getFirst(); + Object newV1 = findVertex(graph, originalV1); + Preconditions.checkState(newV1 != null, "newV1 for "+originalV1+" was not found!"); + graph.addEdge(edge, newV1, v2, inGraph.getEdgeType(edge)); + } else if(clusterGraph.equals(v2)) { + // i need a new v2 + Object originalV2 = originalGraph.getEndpoints(edge).getSecond(); + Object newV2 = findVertex(graph, originalV2); + Preconditions.checkState(newV2 != null, "newV2 for "+originalV2+" was not found!"); + graph.addEdge(edge, v1, newV2, inGraph.getEdgeType(edge)); + } else { + graph.addEdge(edge, v1, v2, inGraph.getEdgeType(edge)); + } + } + } + } + } + return graph; + } + Object findVertex(Graph inGraph, Object vertex) { + Collection vertices = inGraph.getVertices(); + if(vertices.contains(vertex)) { + return vertex; + } + for(Object v : vertices) { + if(v instanceof Graph) { + Graph g = (Graph)v; + if(contains(g, vertex)) { + return v; + } + } + } + return null; + } + + private boolean contains(Graph inGraph, Object vertex) { + boolean contained = false; + if(inGraph.getVertices().contains(vertex)) return true; + for(Object v : inGraph.getVertices()) { + if(v instanceof Graph) { + contained |= contains((Graph)v, vertex); + } + } + return contained; + } + + public Graph getClusterGraph(Graph inGraph, Collection picked) { + Graph clusterGraph; + try { + clusterGraph = createGraph(); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + for(Object v : picked) { + clusterGraph.addVertex(v); + Collection edges = inGraph.getIncidentEdges(v); + for(Object edge : edges) { + Pair endpoints = inGraph.getEndpoints(edge); + Object v1 = endpoints.getFirst(); + Object v2 = endpoints.getSecond(); + if(picked.containsAll(endpoints)) { + clusterGraph.addEdge(edge, v1, v2, inGraph.getEdgeType(edge)); + } + } + } + return clusterGraph; + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Visualization mechanisms relating to grouping or hiding specified element sets. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/TreeCollapser.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/TreeCollapser.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/TreeCollapser.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/subLayout/TreeCollapser.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 23, 2005 + */ +package edu.uci.ics.jung.visualization.subLayout; + +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.graph.Forest; +import edu.uci.ics.jung.graph.util.TreeUtils; + +public class TreeCollapser { + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void collapse(Layout layout, Forest tree, Object subRoot) throws InstantiationException, IllegalAccessException { + + // get a sub tree from subRoot + Forest subTree = TreeUtils.getSubTree(tree, subRoot); + Object parent = null; + Object edge = null; + if(tree.getPredecessorCount(subRoot) > 0) { + parent = tree.getPredecessors(subRoot).iterator().next(); + edge = tree.getInEdges(subRoot).iterator().next(); + } + tree.removeVertex(subRoot); + if(parent != null) { + tree.addEdge(edge, parent, subTree); + } else { + tree.addVertex(subTree); + } + + layout.setLocation(subTree, (Point2D)layout.apply(subRoot)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void expand(Forest tree, Forest subTree) { + + Object parent = null; + Object edge = null; + if(tree.getPredecessorCount(subTree) > 0) { + parent = tree.getPredecessors(subTree).iterator().next(); + edge = tree.getInEdges(subTree).iterator().next(); + } + tree.removeVertex(subTree); + TreeUtils.addSubTree(tree, subTree, parent, edge); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AbstractLensSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AbstractLensSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AbstractLensSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AbstractLensSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 21, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.geom.RectangularShape; + +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.VisualizationServer.Paintable; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +/** + * A class to make it easy to add an + * examining lens to a jung graph application. See HyperbolicTransformerDemo, + * ViewLensSupport and LayoutLensSupport + * for examples of how to use it. + * + * @author Tom Nelson + */ +public abstract class AbstractLensSupport implements LensSupport { + + protected VisualizationViewer vv; + protected VisualizationViewer.GraphMouse graphMouse; + protected LensTransformer lensTransformer; + protected ModalGraphMouse lensGraphMouse; + protected Lens lens; + protected LensControls lensControls; + protected String defaultToolTipText; + + protected static final String instructions = + "

        Mouse-Drag the Lens center to move it

        "+ + "Mouse-Drag the Lens edge to resize it

        "+ + "Ctrl+MouseWheel to change magnification

        "; + + /** + * create the base class, setting common members and creating + * a custom GraphMouse + * @param vv the VisualizationViewer to work on + * @param lensGraphMouse the GraphMouse instance to use for the lens + */ + public AbstractLensSupport(VisualizationViewer vv, ModalGraphMouse lensGraphMouse) { + this.vv = vv; + this.graphMouse = vv.getGraphMouse(); + this.defaultToolTipText = vv.getToolTipText(); + this.lensGraphMouse = lensGraphMouse; + } + + public void activate(boolean state) { + if(state) activate(); + else deactivate(); + } + + public LensTransformer getLensTransformer() { + return lensTransformer; + } + + /** + * @return the hyperbolicGraphMouse. + */ + public ModalGraphMouse getGraphMouse() { + return lensGraphMouse; + } + + /** + * the background for the hyperbolic projection + * @author Tom Nelson + */ + public static class Lens implements Paintable { + LensTransformer lensTransformer; + RectangularShape lensShape; + Paint paint = Color.decode("0xdddddd"); + + public Lens(LensTransformer lensTransformer) { + this.lensTransformer = lensTransformer; + this.lensShape = lensTransformer.getLensShape(); + } + + /** + * @return the paint + */ + public Paint getPaint() { + return paint; + } + + /** + * @param paint the paint to set + */ + public void setPaint(Paint paint) { + this.paint = paint; + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g2d.setPaint(paint); + g2d.fill(lensShape); + } + + public boolean useTransform() { + return true; + } + } + + /** + * the background for the hyperbolic projection + * @author Tom Nelson + * + * + */ + public static class LensControls implements Paintable { + LensTransformer lensTransformer; + RectangularShape lensShape; + Paint paint = Color.gray; + + public LensControls(LensTransformer lensTransformer) { + this.lensTransformer = lensTransformer; + this.lensShape = lensTransformer.getLensShape(); + } + + /** + * @return the paint + */ + public Paint getPaint() { + return paint; + } + + /** + * @param paint the paint to set + */ + public void setPaint(Paint paint) { + this.paint = paint; + } + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + g2d.setPaint(paint); + g2d.draw(lensShape); + int centerX = (int)Math.round(lensShape.getCenterX()); + int centerY = (int)Math.round(lensShape.getCenterY()); + g.drawOval(centerX-10, centerY-10, 20, 20); + } + + public boolean useTransform() { + return true; + } + } + + /** + * @return the lens + */ + public Lens getLens() { + return lens; + } + + /** + * @param lens the lens to set + */ + public void setLens(Lens lens) { + this.lens = lens; + } + + /** + * @return the lensControls + */ + public LensControls getLensControls() { + return lensControls; + } + + /** + * @param lensControls the lensControls to set + */ + public void setLensControls(LensControls lensControls) { + this.lensControls = lensControls; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AffineTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AffineTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AffineTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/AffineTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 16, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.NoninvertibleTransformException; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; + +/** + * + * Provides methods to map points from one coordinate system to + * another, by delegating to a wrapped AffineTransform (uniform) + * and its inverse. + * + * @author Tom Nelson + */ +public class AffineTransformer implements BidirectionalTransformer, ShapeTransformer { + + protected AffineTransform inverse; + + /** + * The AffineTransform to use; initialized to identity. + * + */ + protected AffineTransform transform = new AffineTransform(); + + /** + * Create an instance that does not transform points. + */ + public AffineTransformer() { + // nothing left to do + } + + /** + * Create an instance with the supplied transform. + * @param transform the transform to use + */ + public AffineTransformer(AffineTransform transform) { + if(transform != null) + this.transform = transform; + } + + /** + * @return Returns the transform. + */ + public AffineTransform getTransform() { + return transform; + } + /** + * @param transform The transform to set. + */ + public void setTransform(AffineTransform transform) { + this.transform = transform; + } + + /** + * applies the inverse transform to the supplied point + * @param p the point to transform + * @return the transformed point + */ + public Point2D inverseTransform(Point2D p) { + + return getInverse().transform(p, null); + } + + public AffineTransform getInverse() { + if(inverse == null) { + try { + inverse = transform.createInverse(); + } catch (NoninvertibleTransformException e) { + e.printStackTrace(); + } + } + return inverse; + } + + /** + * @return the transform's x scale value + */ + public double getScaleX() { + return transform.getScaleX(); + } + + /** + * @return the transform's y scale value + */ + public double getScaleY() { + return transform.getScaleY(); + } + + /** + * @return the transform's overall scale magnitude + */ + public double getScale() { + return Math.sqrt(transform.getDeterminant()); + } + + /** + * @return the transform's x shear value + */ + public double getShearX() { + return transform.getShearX(); + } + + /** + * @return the transform's y shear value + */ + public double getShearY() { + return transform.getShearY(); + } + + /** + * @return the transform's x translate value + */ + public double getTranslateX() { + return transform.getTranslateX(); + } + + /** + * @return the transform's y translate value + */ + public double getTranslateY() { + return transform.getTranslateY(); + } + + /** + * Applies the transform to the supplied point. + * + * @param p the point to be transformed + * @return the transformed point + */ + public Point2D transform(Point2D p) { + if(p == null) return null; + return transform.transform(p, null); + } + + /** + * Transform the supplied shape from graph (layout) to screen (view) coordinates. + * + * @return the GeneralPath of the transformed shape + */ + public Shape transform(Shape shape) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + for(PathIterator iterator=shape.getPathIterator(null); + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = transform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = transform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = transform(new Point2D.Float(coords[0], coords[1])); + Point2D q = transform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = transform(new Point2D.Float(coords[0], coords[1])); + q = transform(new Point2D.Float(coords[2], coords[3])); + Point2D r = transform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + + /** + * Transform the supplied shape from screen (view) to graph (layout) coordinates. + * + * @return the GeneralPath of the transformed shape + */ + public Shape inverseTransform(Shape shape) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + for(PathIterator iterator=shape.getPathIterator(null); + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = inverseTransform(new Point2D.Float(coords[0], coords[1])); + Point2D q = inverseTransform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = inverseTransform(new Point2D.Float(coords[0], coords[1])); + q = inverseTransform(new Point2D.Float(coords[2], coords[3])); + Point2D r = inverseTransform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + + public double getRotation() { + double[] unitVector = new double[]{0,0,1,0}; + double[] result = new double[4]; + + transform.transform(unitVector, 0, result, 0, 2); + + double dy = Math.abs(result[3] - result[1]); + double length = Point2D.distance(result[0], result[1], result[2], result[3]); + double rotation = Math.asin(dy / length); + + if (result[3] - result[1] > 0) { + if (result[2] - result[0] < 0) { + rotation = Math.PI - rotation; + } + } else { + if (result[2] - result[0] > 0) { + rotation = 2 * Math.PI - rotation; + } else { + rotation = rotation + Math.PI; + } + } + + return rotation; + } + + @Override + public String toString() { + return "Transformer using "+transform; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/BidirectionalTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/BidirectionalTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/BidirectionalTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/BidirectionalTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 16, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.geom.Point2D; + +/** + * Provides methods to map points from one coordinate system to + * another: graph to screen and screen to graph. + * + * @author Tom Nelson + */ +public interface BidirectionalTransformer { + + /** + * convert the supplied graph coordinate to the screen coordinate + * @param p graph point to convert + * @return screen point + */ + Point2D transform(Point2D p); + + /** + * convert the supplied screen coordinate to the graph coordinate. + * @param p screen point to convert + * @return the graph point + */ + Point2D inverseTransform(Point2D p); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/HyperbolicTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/HyperbolicTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/HyperbolicTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/HyperbolicTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Component; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; + +/** + * HyperbolicTransformer wraps a MutableAffineTransformer and modifies + * the transform and inverseTransform methods so that they create a + * fisheye projection of the graph points, with points near the + * center spread out and points near the edges collapsed onto the + * circumference of an ellipse. + * + * HyperbolicTransformer is not an affine transform, but it uses an + * affine transform to cause translation, scaling, rotation, and shearing + * while applying a non-affine hyperbolic filter in its transform and + * inverseTransform methods. + * + * @author Tom Nelson + */ +public class HyperbolicTransformer extends LensTransformer implements MutableTransformer { + /** + * create an instance, setting values from the passed component + * and registering to listen for size changes on the component + * @param component the component used for rendering + */ + public HyperbolicTransformer(Component component) { + this(component, new MutableAffineTransformer()); + } + + /** + * Create an instance with a possibly shared transform. + * + * @param component the component used for rendering + * @param delegate the transformer to use + */ + public HyperbolicTransformer(Component component, MutableTransformer delegate) { + super(component, delegate); + } + + /** + * override base class transform to project the fisheye effect + */ + public Point2D transform(Point2D graphPoint) { + if(graphPoint == null) return null; + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + // transform the point from the graph to the view + Point2D viewPoint = delegate.transform(graphPoint); + // calculate point from center + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + double theta = polar.getTheta(); + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint; + + double mag = Math.tan(Math.PI/2*magnification); + radius *= mag; + + radius = Math.min(radius, viewRadius); + radius /= viewRadius; + radius *= Math.PI/2; + radius = Math.abs(Math.atan(radius)); + radius *= viewRadius; + Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + + /** + * override base class to un-project the fisheye effect + */ + public Point2D inverseTransform(Point2D viewPoint) { + + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + + double radius = polar.getRadius(); + if(radius > viewRadius) return delegate.inverseTransform(viewPoint); + + radius /= viewRadius; + radius = Math.abs(Math.tan(radius)); + radius /= Math.PI/2; + radius *= viewRadius; + double mag = Math.tan(Math.PI/2*magnification); + radius /= mag; + polar.setRadius(radius); + Point2D projectedPoint = PolarPoint.polarToCartesian(polar); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return delegate.inverseTransform(translatedBack); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LayoutLensSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LayoutLensSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LayoutLensSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LayoutLensSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 21, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Dimension; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse; +import edu.uci.ics.jung.visualization.picking.LayoutLensShapePickSupport; +/** + * A class to make it easy to add an + * examining lens to a jung graph application. See HyperbolicTransformerDemo + * for an example of how to use it. + * + * @author Tom Nelson + * + * + */ +public class LayoutLensSupport extends AbstractLensSupport + implements LensSupport { + + protected GraphElementAccessor pickSupport; + + public LayoutLensSupport(VisualizationViewer vv) { + this(vv, new HyperbolicTransformer( + vv, vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT)), + new ModalLensGraphMouse()); + } + + /** + * Create an instance with the specified parameters. + * + * @param vv the visualization viewer used for rendering + * @param lensTransformer the lens transformer to use + * @param lensGraphMouse the lens input handler + */ + public LayoutLensSupport(VisualizationViewer vv, LensTransformer lensTransformer, + ModalGraphMouse lensGraphMouse) { + super(vv, lensGraphMouse); + this.lensTransformer = lensTransformer; + this.pickSupport = vv.getPickSupport(); + + Dimension d = vv.getSize(); + if(d.width <= 0 || d.height <= 0) { + d = vv.getPreferredSize(); + } + lensTransformer.setViewRadius(d.width/5); + } + + public void activate() { + if(lens == null) { + lens = new Lens(lensTransformer); + } + if(lensControls == null) { + lensControls = new LensControls(lensTransformer); + } + vv.getRenderContext().setPickSupport(new LayoutLensShapePickSupport(vv)); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.LAYOUT, lensTransformer); + vv.prependPreRenderPaintable(lens); + vv.addPostRenderPaintable(lensControls); + vv.setGraphMouse(lensGraphMouse); + vv.setToolTipText(instructions); + vv.repaint(); + } + + public void deactivate() { + if(lensTransformer != null) { + vv.removePreRenderPaintable(lens); + vv.removePostRenderPaintable(lensControls); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.LAYOUT, lensTransformer.getDelegate()); + } + vv.getRenderContext().setPickSupport(pickSupport); + vv.setToolTipText(defaultToolTipText); + vv.setGraphMouse(graphMouse); + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 5, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; + +/** + * basic API for implementing lens projection support + * + * @author Tom Nelson + * + */ +public interface LensSupport { + + void activate(); + void deactivate(); + void activate(boolean state); + LensTransformer getLensTransformer(); + + ModalGraphMouse getGraphMouse(); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/LensTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Shape; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +/** + * LensTransformer wraps a MutableAffineTransformer and modifies + * the transform and inverseTransform methods so that they create a + * projection of the graph points within an elliptical lens. + * + * LensTransformer uses an + * affine transform to cause translation, scaling, rotation, and shearing + * while applying a possibly non-affine filter in its transform and + * inverseTransform methods. + * + * @author Tom Nelson + */ +public abstract class LensTransformer extends MutableTransformerDecorator implements MutableTransformer { + + /** + * the area affected by the transform + */ + protected RectangularShape lensShape = new Ellipse2D.Float(); + + protected float magnification = 0.7f; + + /** + * Create an instance with a possibly shared transform. + * + * @param component the component used for rendering + * @param delegate the transformer to use + */ + public LensTransformer(Component component, MutableTransformer delegate) { + super(delegate); + setComponent(component); + component.addComponentListener(new ComponentListenerImpl()); + } + + /** + * Set values from the passed component. + * @param component the component used for rendering + */ + private void setComponent(Component component) { + Dimension d = component.getSize(); + if(d.width <= 0 || d.height <= 0) { + d = component.getPreferredSize(); + } + float ewidth = d.width/1.5f; + float eheight = d.height/1.5f; + lensShape.setFrame(d.width/2-ewidth/2, d.height/2-eheight/2, ewidth, eheight); + } + + public float getMagnification() { + return magnification; + } + + public void setMagnification(float magnification) { + this.magnification = magnification; + } + + public Point2D getViewCenter() { + return new Point2D.Double(lensShape.getCenterX(), lensShape.getCenterY()); + } + + public void setViewCenter(Point2D viewCenter) { + double width = lensShape.getWidth(); + double height = lensShape.getHeight(); + lensShape.setFrame(viewCenter.getX()-width/2, + viewCenter.getY()-height/2, + width, height); + } + + public double getViewRadius() { + return lensShape.getHeight()/2; + } + + public void setViewRadius(double viewRadius) { + double x = lensShape.getCenterX(); + double y = lensShape.getCenterY(); + double viewRatio = getRatio(); + lensShape.setFrame(x-viewRadius/viewRatio, + y-viewRadius, + 2*viewRadius/viewRatio, + 2*viewRadius); + } + + /** + * @return the ratio between the lens height and lens width + */ + public double getRatio() { + return lensShape.getHeight()/lensShape.getWidth(); + } + + public void setLensShape(RectangularShape ellipse) { + this.lensShape = ellipse; + } + public RectangularShape getLensShape() { + return lensShape; + } + public void setToIdentity() { + this.delegate.setToIdentity(); + } + + /** + * react to size changes on a component + */ + protected class ComponentListenerImpl extends ComponentAdapter { + public void componentResized(ComponentEvent e) { + setComponent(e.getComponent()); + } + } + + /** + * override base class transform to project the fisheye effect + */ + public abstract Point2D transform(Point2D graphPoint); + + /** + * override base class to un-project the fisheye effect + */ + public abstract Point2D inverseTransform(Point2D viewPoint); + + public double getDistanceFromCenter(Point2D p) { + + double dx = lensShape.getCenterX()-p.getX(); + double dy = lensShape.getCenterY()-p.getY(); + dx *= getRatio(); + return Math.sqrt(dx*dx + dy*dy); + } + + /** + * return the supplied shape, translated to the coordinates + * that result from calling transform on its center + */ + public Shape transform(Shape shape) { + Rectangle2D bounds = shape.getBounds2D(); + Point2D center = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); + Point2D newCenter = transform(center); + double dx = newCenter.getX()-center.getX(); + double dy = newCenter.getY()-center.getY(); + AffineTransform at = AffineTransform.getTranslateInstance(dx,dy); + return at.createTransformedShape(shape); + } + + /** + * Returns the supplied shape, translated to the coordinates + * that result from calling inverseTransform on its center. + */ + public Shape inverseTransform(Shape shape) { + Rectangle2D bounds = shape.getBounds2D(); + Point2D center = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); + Point2D newCenter = inverseTransform(center); + double dx = newCenter.getX()-center.getX(); + double dy = newCenter.getY()-center.getY(); + AffineTransform at = AffineTransform.getTranslateInstance(dx,dy); + return at.createTransformedShape(shape); + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MagnifyTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MagnifyTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MagnifyTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MagnifyTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Component; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; + +/** + * MagnifyTransformer wraps a MutableAffineTransformer and modifies + * the transform and inverseTransform methods so that they create an + * enlarging projection of the graph points. + * + * MagnifyTransformer uses an + * affine transform to cause translation, scaling, rotation, and shearing + * while applying a separate magnification filter in its transform and + * inverseTransform methods. + * + * @author Tom Nelson + */ +public class MagnifyTransformer extends LensTransformer implements MutableTransformer { + /** + * Create an instance, setting values from the passed component + * and registering to listen for size changes on the component. + * + * @param component the component used for rendering + */ + public MagnifyTransformer(Component component) { + this(component, new MutableAffineTransformer()); + } + + /** + * Create an instance with a possibly shared transform. + * + * @param component the component used for rendering + * @param delegate the transformer to use + */ + public MagnifyTransformer(Component component, MutableTransformer delegate) { + super(component, delegate); + this.magnification = 3.f; + } + + /** + * override base class transform to project the fisheye effect + */ + public Point2D transform(Point2D graphPoint) { + if(graphPoint == null) return null; + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + // transform the point from the graph to the view + Point2D viewPoint = delegate.transform(graphPoint); + // calculate point from center + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + double theta = polar.getTheta(); + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint; + + double mag = magnification; + radius *= mag; + + radius = Math.min(radius, viewRadius); + Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + + /** + * override base class to un-project the fisheye effect + */ + public Point2D inverseTransform(Point2D viewPoint) { + + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + + double radius = polar.getRadius(); + if(radius > viewRadius) return delegate.inverseTransform(viewPoint); + + double mag = magnification; + radius /= mag; + polar.setRadius(radius); + Point2D projectedPoint = PolarPoint.polarToCartesian(polar); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return delegate.inverseTransform(translatedBack); + } + + /** + * Magnifies the point, without considering the Lens. + * @param graphPoint the point to transform via magnification + * @return the transformed point + */ + public Point2D magnify(Point2D graphPoint) { + if(graphPoint == null) return null; + Point2D viewCenter = getViewCenter(); + double ratio = getRatio(); + // transform the point from the graph to the view + Point2D viewPoint = graphPoint; + // calculate point from center + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + double theta = polar.getTheta(); + double radius = polar.getRadius(); + + double mag = magnification; + radius *= mag; + +// radius = Math.min(radius, viewRadius); + Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableAffineTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableAffineTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableAffineTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableAffineTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 16, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; +import edu.uci.ics.jung.visualization.util.DefaultChangeEventSupport; + +/** + * + * Provides methods to mutate the AffineTransform used by AffineTransformer + * base class to map points from one coordinate system to + * another. + * + * + * @author Tom Nelson + * + * + */ +public class MutableAffineTransformer extends AffineTransformer +implements MutableTransformer, ShapeTransformer, ChangeEventSupport { + + protected ChangeEventSupport changeSupport = + new DefaultChangeEventSupport(this); + + /** + * create an instance that does not transform points + */ + public MutableAffineTransformer() { + // nothing left to do + } + + /** + * Create an instance with the supplied transform + * @param transform the transform to use + */ + public MutableAffineTransformer(AffineTransform transform) { + super(transform); + } + + public String toString() { + return "MutableAffineTransformer using "+transform; + } + + /** + * setter for the scale + * fires a PropertyChangeEvent with the AffineTransforms representing + * the previous and new values for scale and offset + * @param scalex the amount to scale in the x direction + * @param scaley the amount to scale in the y direction + * @param from the point to transform + */ + public void scale(double scalex, double scaley, Point2D from) { + AffineTransform xf = AffineTransform.getTranslateInstance(from.getX(),from.getY()); + xf.scale(scalex, scaley); + xf.translate(-from.getX(), -from.getY()); + inverse = null; + transform.preConcatenate(xf); + fireStateChanged(); + } + + /** + * setter for the scale + * fires a PropertyChangeEvent with the AffineTransforms representing + * the previous and new values for scale and offset + * @param scalex the amount to scale in the x direction + * @param scaley the amount to scale in the y direction + * @param from the point to transform + */ + public void setScale(double scalex, double scaley, Point2D from) { + transform.setToIdentity(); + scale(scalex, scaley, from); + } + + /** + * shears the transform by passed parameters + * @param shx x value to shear + * @param shy y value to shear + * @param from the point to transform + */ + public void shear(double shx, double shy, Point2D from) { + inverse = null; + AffineTransform at = + AffineTransform.getTranslateInstance(from.getX(), from.getY()); + at.shear(shx, shy); + at.translate(-from.getX(), -from.getY()); + transform.preConcatenate(at); + fireStateChanged(); + } + + /** + * Replace the Transform's translate x and y values + * with the passed values, leaving the scale values + * unchanged. + * @param tx the x value of the translation + * @param ty the y value of the translation + */ + public void setTranslate(double tx, double ty) { + float scalex = (float) transform.getScaleX(); + float scaley = (float) transform.getScaleY(); + float shearx = (float) transform.getShearX(); + float sheary = (float) transform.getShearY(); + inverse = null; + transform.setTransform(scalex, + sheary, + shearx, + scaley, + tx, ty); + fireStateChanged(); + } + + /** + * Apply the passed values to the current Transform + * @param offsetx the x-value + * @param offsety the y-value + */ + public void translate(double offsetx, double offsety) { + inverse = null; + transform.translate(offsetx, offsety); + fireStateChanged(); + } + + /** + * preconcatenates the rotation at the supplied point with the current transform + * @param theta the angle by which to rotate the point + * @param from the point to transform + */ + public void rotate(double theta, Point2D from) { + AffineTransform rotate = + AffineTransform.getRotateInstance(theta, from.getX(), from.getY()); + inverse = null; + transform.preConcatenate(rotate); + + fireStateChanged(); + } + + /** + * rotates the current transform at the supplied points + * @param radians angle by which to rotate the supplied coordinates + * @param x the x coordinate of the point to transform + * @param y the y coordinate of the point to transform + */ + public void rotate(double radians, double x, double y) { + inverse = null; + transform.rotate(radians, x, y); + fireStateChanged(); + } + + public void concatenate(AffineTransform xform) { + inverse = null; + transform.concatenate(xform); + fireStateChanged(); + + } + public void preConcatenate(AffineTransform xform) { + inverse = null; + transform.preConcatenate(xform); + fireStateChanged(); + } + + + /** + * Adds a ChangeListener. + * @param l the listener to be added + */ + public void addChangeListener(ChangeListener l) { + changeSupport.addChangeListener(l); + } + + /** + * Removes a ChangeListener. + * @param l the listener to be removed + */ + public void removeChangeListener(ChangeListener l) { + changeSupport.removeChangeListener(l); + } + + /** + * Returns an array of all the ChangeListeners added + * with addChangeListener(). + * + * @return all of the ChangeListeners added or an empty + * array if no listeners have been added + */ + public ChangeListener[] getChangeListeners() { + return changeSupport.getChangeListeners(); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * @see EventListenerList + */ + public void fireStateChanged() { + changeSupport.fireStateChanged(); + } + + public void setToIdentity() { + inverse = null; + transform.setToIdentity(); + fireStateChanged(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformerDecorator.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformerDecorator.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformerDecorator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformerDecorator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import javax.swing.event.ChangeListener; + +/** + * a complete decorator that wraps a MutableTransformer. Subclasses + * use this to allow them to only declare methods they need to change. + * + * @author Tom Nelson + * + */ +public abstract class MutableTransformerDecorator implements MutableTransformer { + + protected MutableTransformer delegate; + + public MutableTransformerDecorator(MutableTransformer delegate) { + if(delegate == null) { + delegate = new MutableAffineTransformer(); + } + this.delegate = delegate; + } + + public MutableTransformer getDelegate() { + return delegate; + } + + public void setDelegate(MutableTransformer delegate) { + this.delegate = delegate; + } + + public void addChangeListener(ChangeListener l) { + delegate.addChangeListener(l); + } + + public void concatenate(AffineTransform transform) { + delegate.concatenate(transform); + } + + public void fireStateChanged() { + delegate.fireStateChanged(); + } + + public ChangeListener[] getChangeListeners() { + return delegate.getChangeListeners(); + } + + public double getScale() { + return delegate.getScale(); + } + + public double getScaleX() { + return delegate.getScaleX(); + } + + public double getScaleY() { + return delegate.getScaleY(); + } + + public double getShearX() { + return delegate.getShearX(); + } + + public double getShearY() { + return delegate.getShearY(); + } + + public AffineTransform getTransform() { + return delegate.getTransform(); + } + + public double getTranslateX() { + return delegate.getTranslateX(); + } + + public double getTranslateY() { + return delegate.getTranslateY(); + } + + public Point2D inverseTransform(Point2D p) { + return delegate.inverseTransform(p); + } + + public Shape inverseTransform(Shape shape) { + return delegate.inverseTransform(shape); + } + + public void preConcatenate(AffineTransform transform) { + delegate.preConcatenate(transform); + } + + public void removeChangeListener(ChangeListener l) { + delegate.removeChangeListener(l); + } + + public void rotate(double radians, Point2D point) { + delegate.rotate(radians, point); + } + + public void scale(double sx, double sy, Point2D point) { + delegate.scale(sx, sy, point); + } + + public void setScale(double sx, double sy, Point2D point) { + delegate.setScale(sx, sy, point); + } + + public void setToIdentity() { + delegate.setToIdentity(); + } + + public void setTranslate(double dx, double dy) { + delegate.setTranslate(dx, dy); + } + + public void shear(double shx, double shy, Point2D from) { + delegate.shear(shx, shy, from); + } + + public Point2D transform(Point2D p) { + return delegate.transform(p); + } + + public Shape transform(Shape shape) { + return delegate.transform(shape); + } + + public void translate(double dx, double dy) { + delegate.translate(dx, dy); + } + + public double getRotation() { + return delegate.getRotation(); + } + + public void rotate(double radians, double x, double y) { + delegate.rotate(radians, x, y); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/MutableTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 3, 2005 + */ + +package edu.uci.ics.jung.visualization.transform; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; + +/** + * Provides an API for the mutation of a Function + * and for adding listeners for changes on the Function + * + * @author Tom Nelson + * + * + */ +public interface MutableTransformer extends ShapeTransformer, ChangeEventSupport { + + void translate(double dx, double dy); + + void setTranslate(double dx, double dy); + + void scale(double sx, double sy, Point2D point); + + void setScale(double sx, double sy, Point2D point); + + void rotate(double radians, Point2D point); + + void rotate(double radians, double x, double y); + + void shear(double shx, double shy, Point2D from); + + void concatenate(AffineTransform transform); + + void preConcatenate(AffineTransform transform); + + double getScaleX(); + + double getScaleY(); + + double getScale(); + + double getTranslateX(); + + double getTranslateY(); + + double getShearX(); + + double getShearY(); + + AffineTransform getTransform(); + + void setToIdentity(); + + double getRotation(); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Visualization mechanisms related to transformations, including lens effects. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Graphics2DWrapper.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Graphics2DWrapper.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Graphics2DWrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Graphics2DWrapper.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,674 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 11, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.RenderingHints.Key; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + + +/** + * a complete wrapping of Graphics2D, useful as a base class. + * Contains no additional methods, other than direct calls + * to the delegate. + * + * @see GraphicsDecorator as an example subclass that + * adds additional methods. + * + * @author Tom Nelson + * + * + */ +public class Graphics2DWrapper { + + protected Graphics2D delegate; + + public Graphics2DWrapper() { + this(null); + } + public Graphics2DWrapper(Graphics2D delegate) { + this.delegate = delegate; + } + + public void setDelegate(Graphics2D delegate) { + this.delegate = delegate; + } + + public Graphics2D getDelegate() { + return delegate; + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#addRenderingHints(java.util.Map) + */ + public void addRenderingHints(Map hints) { + delegate.addRenderingHints(hints); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#clearRect(int, int, int, int) + */ + public void clearRect(int x, int y, int width, int height) { + delegate.clearRect(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#clip(java.awt.Shape) + */ + public void clip(Shape s) { + delegate.clip(s); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#clipRect(int, int, int, int) + */ + public void clipRect(int x, int y, int width, int height) { + delegate.clipRect(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#copyArea(int, int, int, int, int, int) + */ + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + delegate.copyArea(x, y, width, height, dx, dy); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#create() + */ + public Graphics create() { + return delegate.create(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#create(int, int, int, int) + */ + public Graphics create(int x, int y, int width, int height) { + return delegate.create(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#dispose() + */ + public void dispose() { + delegate.dispose(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#draw(java.awt.Shape) + */ + public void draw(Shape s) { + delegate.draw(s); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#draw3DRect(int, int, int, int, boolean) + */ + public void draw3DRect(int x, int y, int width, int height, boolean raised) { + delegate.draw3DRect(x, y, width, height, raised); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawArc(int, int, int, int, int, int) + */ + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + delegate.drawArc(x, y, width, height, startAngle, arcAngle); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawBytes(byte[], int, int, int, int) + */ + public void drawBytes(byte[] data, int offset, int length, int x, int y) { + delegate.drawBytes(data, offset, length, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawChars(char[], int, int, int, int) + */ + public void drawChars(char[] data, int offset, int length, int x, int y) { + delegate.drawChars(data, offset, length, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawGlyphVector(java.awt.font.GlyphVector, float, float) + */ + public void drawGlyphVector(GlyphVector g, float x, float y) { + delegate.drawGlyphVector(g, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawImage(java.awt.image.BufferedImage, java.awt.image.BufferedImageOp, int, int) + */ + public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { + delegate.drawImage(img, op, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawImage(java.awt.Image, java.awt.geom.AffineTransform, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + return delegate.drawImage(img, xform, obs); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, java.awt.Color, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { + return delegate.drawImage(img, x, y, bgcolor, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + return delegate.drawImage(img, x, y, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, java.awt.Color, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { + return delegate.drawImage(img, x, y, width, height, bgcolor, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { + return delegate.drawImage(img, x, y, width, height, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, int, int, int, int, java.awt.Color, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) { + return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawImage(java.awt.Image, int, int, int, int, int, int, int, int, java.awt.image.ImageObserver) + */ + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { + return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawLine(int, int, int, int) + */ + public void drawLine(int x1, int y1, int x2, int y2) { + delegate.drawLine(x1, y1, x2, y2); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawOval(int, int, int, int) + */ + public void drawOval(int x, int y, int width, int height) { + delegate.drawOval(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawPolygon(int[], int[], int) + */ + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { + delegate.drawPolygon(xPoints, yPoints, nPoints); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawPolygon(java.awt.Polygon) + */ + public void drawPolygon(Polygon p) { + delegate.drawPolygon(p); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawPolyline(int[], int[], int) + */ + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) { + delegate.drawPolyline(xPoints, yPoints, nPoints); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawRect(int, int, int, int) + */ + public void drawRect(int x, int y, int width, int height) { + delegate.drawRect(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawRenderableImage(java.awt.image.renderable.RenderableImage, java.awt.geom.AffineTransform) + */ + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + delegate.drawRenderableImage(img, xform); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawRenderedImage(java.awt.image.RenderedImage, java.awt.geom.AffineTransform) + */ + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + delegate.drawRenderedImage(img, xform); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#drawRoundRect(int, int, int, int, int, int) + */ + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + delegate.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, float, float) + */ + public void drawString(AttributedCharacterIterator iterator, float x, float y) { + delegate.drawString(iterator, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawString(java.text.AttributedCharacterIterator, int, int) + */ + public void drawString(AttributedCharacterIterator iterator, int x, int y) { + delegate.drawString(iterator, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawString(java.lang.String, float, float) + */ + public void drawString(String s, float x, float y) { + delegate.drawString(s, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#drawString(java.lang.String, int, int) + */ + public void drawString(String str, int x, int y) { + delegate.drawString(str, x, y); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + return delegate.equals(obj); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#fill(java.awt.Shape) + */ + public void fill(Shape s) { + delegate.fill(s); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#fill3DRect(int, int, int, int, boolean) + */ + public void fill3DRect(int x, int y, int width, int height, boolean raised) { + delegate.fill3DRect(x, y, width, height, raised); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillArc(int, int, int, int, int, int) + */ + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + delegate.fillArc(x, y, width, height, startAngle, arcAngle); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillOval(int, int, int, int) + */ + public void fillOval(int x, int y, int width, int height) { + delegate.fillOval(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillPolygon(int[], int[], int) + */ + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) { + delegate.fillPolygon(xPoints, yPoints, nPoints); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillPolygon(java.awt.Polygon) + */ + public void fillPolygon(Polygon p) { + delegate.fillPolygon(p); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillRect(int, int, int, int) + */ + public void fillRect(int x, int y, int width, int height) { + delegate.fillRect(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#fillRoundRect(int, int, int, int, int, int) + */ + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + delegate.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#finalize() + */ + public void finalize() { + delegate.finalize(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getBackground() + */ + public Color getBackground() { + return delegate.getBackground(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getClip() + */ + public Shape getClip() { + return delegate.getClip(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getClipBounds() + */ + public Rectangle getClipBounds() { + return delegate.getClipBounds(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getClipBounds(java.awt.Rectangle) + */ + public Rectangle getClipBounds(Rectangle r) { + return delegate.getClipBounds(r); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getClipRect() + */ + @SuppressWarnings("deprecation") + public Rectangle getClipRect() { + return delegate.getClipRect(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getColor() + */ + public Color getColor() { + return delegate.getColor(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getComposite() + */ + public Composite getComposite() { + return delegate.getComposite(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getDeviceConfiguration() + */ + public GraphicsConfiguration getDeviceConfiguration() { + return delegate.getDeviceConfiguration(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getFont() + */ + public Font getFont() { + return delegate.getFont(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getFontMetrics() + */ + public FontMetrics getFontMetrics() { + return delegate.getFontMetrics(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#getFontMetrics(java.awt.Font) + */ + public FontMetrics getFontMetrics(Font f) { + return delegate.getFontMetrics(f); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getFontRenderContext() + */ + public FontRenderContext getFontRenderContext() { + return delegate.getFontRenderContext(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getPaint() + */ + public Paint getPaint() { + return delegate.getPaint(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getRenderingHint(java.awt.RenderingHints.Key) + */ + public Object getRenderingHint(Key hintKey) { + return delegate.getRenderingHint(hintKey); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getRenderingHints() + */ + public RenderingHints getRenderingHints() { + return delegate.getRenderingHints(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getStroke() + */ + public Stroke getStroke() { + return delegate.getStroke(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#getTransform() + */ + public AffineTransform getTransform() { + return delegate.getTransform(); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return delegate.hashCode(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#hit(java.awt.Rectangle, java.awt.Shape, boolean) + */ + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + return delegate.hit(rect, s, onStroke); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#hitClip(int, int, int, int) + */ + public boolean hitClip(int x, int y, int width, int height) { + return delegate.hitClip(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#rotate(double, double, double) + */ + public void rotate(double theta, double x, double y) { + delegate.rotate(theta, x, y); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#rotate(double) + */ + public void rotate(double theta) { + delegate.rotate(theta); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#scale(double, double) + */ + public void scale(double sx, double sy) { + delegate.scale(sx, sy); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setBackground(java.awt.Color) + */ + public void setBackground(Color color) { + delegate.setBackground(color); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setClip(int, int, int, int) + */ + public void setClip(int x, int y, int width, int height) { + delegate.setClip(x, y, width, height); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setClip(java.awt.Shape) + */ + public void setClip(Shape clip) { + delegate.setClip(clip); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setColor(java.awt.Color) + */ + public void setColor(Color c) { + delegate.setColor(c); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setComposite(java.awt.Composite) + */ + public void setComposite(Composite comp) { + delegate.setComposite(comp); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setFont(java.awt.Font) + */ + public void setFont(Font font) { + delegate.setFont(font); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setPaint(java.awt.Paint) + */ + public void setPaint(Paint paint) { + delegate.setPaint(paint); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setPaintMode() + */ + public void setPaintMode() { + delegate.setPaintMode(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setRenderingHint(java.awt.RenderingHints.Key, java.lang.Object) + */ + public void setRenderingHint(Key hintKey, Object hintValue) { + delegate.setRenderingHint(hintKey, hintValue); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setRenderingHints(java.util.Map) + */ + public void setRenderingHints(Map hints) { + delegate.setRenderingHints(hints); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setStroke(java.awt.Stroke) + */ + public void setStroke(Stroke s) { + delegate.setStroke(s); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#setTransform(java.awt.geom.AffineTransform) + */ + public void setTransform(AffineTransform Tx) { + delegate.setTransform(Tx); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#setXORMode(java.awt.Color) + */ + public void setXORMode(Color c1) { + delegate.setXORMode(c1); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#shear(double, double) + */ + public void shear(double shx, double shy) { + delegate.shear(shx, shy); + } + + /* (non-Javadoc) + * @see java.awt.Graphics#toString() + */ + public String toString() { + return delegate.toString(); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#transform(java.awt.geom.AffineTransform) + */ + public void transform(AffineTransform Tx) { + delegate.transform(Tx); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#translate(double, double) + */ + public void translate(double tx, double ty) { + delegate.translate(tx, ty); + } + + /* (non-Javadoc) + * @see java.awt.Graphics2D#translate(int, int) + */ + public void translate(int x, int y) { + delegate.translate(x, y); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/GraphicsDecorator.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/GraphicsDecorator.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/GraphicsDecorator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/GraphicsDecorator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 11, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Shape; + +import javax.swing.CellRendererPane; +import javax.swing.Icon; + + +/** + * an extendion of Graphics2DWrapper that adds enhanced + * methods for drawing icons and components + * + * @see TransformingGraphics as an example subclass + * + * @author Tom Nelson + * + * + */ +public class GraphicsDecorator extends Graphics2DWrapper { + + public GraphicsDecorator() { + this(null); + } + public GraphicsDecorator(Graphics2D delegate) { + super(delegate); + } + + public void draw(Icon icon, Component c, Shape clip, int x, int y) { + int w = icon.getIconWidth(); + int h = icon.getIconHeight(); + icon.paintIcon(c, delegate, x-w/2, y-h/2); + } + + public void draw(Component c, CellRendererPane rendererPane, + int x, int y, int w, int h, boolean shouldValidate) { + rendererPane.paintComponent(delegate, c, c.getParent(), x, y, w, h, shouldValidate); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/HyperbolicShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/HyperbolicShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/HyperbolicShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/HyperbolicShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Component; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + + +/** + * HyperbolicShapeTransformer extends HyperbolicTransformer and + * adds implementations for methods in ShapeFlatnessTransformer. + * It modifies the shapes (Vertex, Edge, and Arrowheads) so that + * they are distorted by the hyperbolic transformation + * + * @author Tom Nelson + * + * + */ +public class HyperbolicShapeTransformer extends HyperbolicTransformer + implements ShapeFlatnessTransformer { + + /** + * Create an instance, setting values from the passed component + * and registering to listen for size changes on the component. + * @param component the component in which rendering takes place + */ + public HyperbolicShapeTransformer(Component component) { + this(component, null); + } + + /** + * Create an instance, setting values from the passed component + * and registering to listen for size changes on the component, + * with a possibly shared transform delegate. + * @param component the component in which rendering takes place + * @param delegate the transformer to use + */ + public HyperbolicShapeTransformer(Component component, MutableTransformer delegate) { + super(component, delegate); + } + + /** + * Transform the supplied shape with the overridden transform + * method so that the shape is distorted by the hyperbolic + * transform. + * @param shape a shape to transform + * @return a GeneralPath for the transformed shape + */ + public Shape transform(Shape shape) { + return transform(shape, 0); + } + public Shape transform(Shape shape, float flatness) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + PathIterator iterator = null; + if(flatness == 0) { + iterator = shape.getPathIterator(null); + } else { + iterator = shape.getPathIterator(null, flatness); + } + for( ; + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = _transform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + Point2D q = _transform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + q = _transform(new Point2D.Float(coords[2], coords[3])); + Point2D r = _transform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + + public Shape inverseTransform(Shape shape) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + for(PathIterator iterator=shape.getPathIterator(null); + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + Point2D q = _inverseTransform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + q = _inverseTransform(new Point2D.Float(coords[2], coords[3])); + Point2D r = _inverseTransform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + /** + * override base class transform to project the fisheye effect + */ + private Point2D _transform(Point2D graphPoint) { + if(graphPoint == null) return null; + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + // transform the point from the graph to the view + Point2D viewPoint = graphPoint;//delegate.transform(graphPoint); + // calculate point from center + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + double theta = polar.getTheta(); + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint; + + double mag = Math.tan(Math.PI/2*magnification); + radius *= mag; + + radius = Math.min(radius, viewRadius); + radius /= viewRadius; + radius *= Math.PI/2; + radius = Math.abs(Math.atan(radius)); + radius *= viewRadius; + Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + + /** + * override base class to un-project the fisheye effect + */ + private Point2D _inverseTransform(Point2D viewPoint) { + + viewPoint = delegate.inverseTransform(viewPoint); + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint;//elegate.inverseTransform(viewPoint); + + radius /= viewRadius; + radius = Math.abs(Math.tan(radius)); + radius /= Math.PI/2; + radius *= viewRadius; + double mag = Math.tan(Math.PI/2*magnification); + radius /= mag; + polar.setRadius(radius); + Point2D projectedPoint = PolarPoint.polarToCartesian(polar); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + //delegate.inverseTransform(translatedBack); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Intersector.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Intersector.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Intersector.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/Intersector.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Rectangle; +import java.awt.geom.Line2D; +import java.awt.geom.Point2D; +import java.util.HashSet; +import java.util.Set; + +public class Intersector { + + protected Rectangle rectangle; + Line2D line; + Set points = new HashSet(); + + public Intersector(Rectangle rectangle) { + this.rectangle = rectangle; + } + + public Intersector(Rectangle rectangle, Line2D line) { + this.rectangle = rectangle; + intersectLine(line); + } + + public void intersectLine(Line2D line) { + this.line = line; + points.clear(); + float rx0 = (float) rectangle.getMinX(); + float ry0 = (float) rectangle.getMinY(); + float rx1 = (float) rectangle.getMaxX(); + float ry1 = (float) rectangle.getMaxY(); + + float x1 = (float) line.getX1(); + float y1 = (float) line.getY1(); + float x2 = (float) line.getX2(); + float y2 = (float) line.getY2(); + + float dy = y2 - y1; + float dx = x2 - x1; + + if(dx != 0) { + float m = dy/dx; + float b = y1 - m*x1; + + // base of rect where y == ry0 + float x = (ry0 - b) / m; + + if(rx0 <= x && x <= rx1) { + points.add(new Point2D.Float(x, ry0)); + } + + // top where y == ry1 + x = (ry1 - b) / m; + if(rx0 <= x && x <= rx1) { + points.add(new Point2D.Float(x, ry1)); + } + + // left side, where x == rx0 + float y = m * rx0 + b; + if(ry0 <= y && y <= ry1) { + points.add(new Point2D.Float(rx0, y)); + } + + + // right side, where x == rx1 + y = m * rx1 + b; + if(ry0 <= y && y <= ry1) { + points.add(new Point2D.Float(rx1, y)); + } + + } else { + + // base, where y == ry0 + float x = x1; + if(rx0 <= x && x <= rx1) { + points.add(new Point2D.Float(x, ry0)); + } + + // top, where y == ry1 + x = x2; + if(rx0 <= x && x <= rx1) { + points.add(new Point2D.Float(x, ry1)); + } + } + } + public Line2D getLine() { + return line; + } + public Set getPoints() { + return points; + } + public Rectangle getRectangle() { + return rectangle; + } + + public String toString() { + return "Rectangle: "+rectangle+", points:"+points; + } + + public static void main(String[] args) { + Rectangle rectangle = new Rectangle(0,0,10,10); + Line2D line = new Line2D.Float(4,4,5,5); + System.err.println(""+new Intersector(rectangle, line)); + System.err.println(""+new Intersector(rectangle, new Line2D.Float(9,11,11,9))); + System.err.println(""+new Intersector(rectangle, new Line2D.Float(1,1,3,2))); + System.err.println(""+new Intersector(rectangle, new Line2D.Float(4,6,6,4))); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyIconGraphics.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyIconGraphics.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyIconGraphics.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyIconGraphics.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 11, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; +import java.awt.geom.Rectangle2D; + +import javax.swing.Icon; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; + + +/** + * Subclassed to apply a magnification transform to an icon. + * + * @author Tom Nelson + * + * + */ +public class MagnifyIconGraphics extends TransformingFlatnessGraphics { + + public MagnifyIconGraphics(BidirectionalTransformer transformer) { + this(transformer, null); + } + + public MagnifyIconGraphics(BidirectionalTransformer Function, Graphics2D delegate) { + super(Function, delegate); + } + + public void draw(Icon icon, Component c, Shape clip, int x, int y) { + + if(transformer instanceof MagnifyShapeTransformer) { + MagnifyShapeTransformer mst = (MagnifyShapeTransformer)transformer; + int w = icon.getIconWidth(); + int h = icon.getIconHeight(); + Rectangle2D r = new Rectangle2D.Double(x-w/2,y-h/2,w,h); + Shape lens = mst.getLensShape(); + if(lens.intersects(r)) { + // magnify the whole icon + Rectangle2D s = mst.magnify(r).getBounds2D(); + if(lens.intersects(s)) { + clip = mst.transform(clip); + double sx = s.getWidth()/r.getWidth(); + double sy = s.getHeight()/r.getHeight(); + + AffineTransform old = delegate.getTransform(); + AffineTransform xform = new AffineTransform(old); + xform.translate(s.getMinX(), s.getMinY()); + xform.scale(sx, sy); + xform.translate(-s.getMinX(), -s.getMinY()); + Shape oldClip = delegate.getClip(); + delegate.clip(clip); + delegate.setTransform(xform); + icon.paintIcon(c, delegate, (int)s.getMinX(), (int)s.getMinY()); + delegate.setTransform(old); + delegate.setClip(oldClip); + } else { + // clip out the lens so the small icon doesn't get drawn + // inside of it + Shape oldClip = delegate.getClip(); + Area viewBounds = new Area(oldClip); + viewBounds.subtract(new Area(lens)); + delegate.setClip(viewBounds); + icon.paintIcon(c, delegate, (int)r.getMinX(),(int)r.getMinY()); + delegate.setClip(oldClip); + } + + } else { + icon.paintIcon(c, delegate, (int)r.getMinX(),(int)r.getMinY()); + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyImageLensSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyImageLensSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyImageLensSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyImageLensSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 21, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Dimension; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse; +import edu.uci.ics.jung.visualization.picking.ViewLensShapePickSupport; +import edu.uci.ics.jung.visualization.renderers.BasicRenderer; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.ReshapingEdgeRenderer; +import edu.uci.ics.jung.visualization.transform.AbstractLensSupport; +import edu.uci.ics.jung.visualization.transform.LensTransformer; +/** + * Changes various visualization settings to activate or deactivate an + * examining lens for a jung graph application. + * + * @author Tom Nelson + */ +public class MagnifyImageLensSupport extends AbstractLensSupport { + + protected RenderContext renderContext; + protected GraphicsDecorator lensGraphicsDecorator; + protected GraphicsDecorator savedGraphicsDecorator; + protected Renderer renderer; + protected Renderer transformingRenderer; + protected GraphElementAccessor pickSupport; + protected Renderer.Edge savedEdgeRenderer; + protected Renderer.Edge reshapingEdgeRenderer; + + static final String instructions = + "

        Mouse-Drag the Lens center to move it

        "+ + "Mouse-Drag the Lens edge to resize it

        "+ + "Ctrl+MouseWheel to change magnification

        "; + + public MagnifyImageLensSupport(VisualizationViewer vv) { + this(vv, new MagnifyShapeTransformer(vv), + new ModalLensGraphMouse()); + } + + public MagnifyImageLensSupport(VisualizationViewer vv, LensTransformer lensTransformer, + ModalGraphMouse lensGraphMouse) { + super(vv, lensGraphMouse); + this.renderContext = vv.getRenderContext(); + this.pickSupport = renderContext.getPickSupport(); + this.renderer = vv.getRenderer(); + this.transformingRenderer = new BasicRenderer(); + this.savedGraphicsDecorator = renderContext.getGraphicsContext(); + this.lensTransformer = lensTransformer; + this.savedEdgeRenderer = vv.getRenderer().getEdgeRenderer(); + this.reshapingEdgeRenderer = new ReshapingEdgeRenderer(); + this.reshapingEdgeRenderer.setEdgeArrowRenderingSupport(savedEdgeRenderer.getEdgeArrowRenderingSupport()); + + Dimension d = vv.getSize(); + if(d.width == 0 || d.height == 0) { + d = vv.getPreferredSize(); + } + lensTransformer.setViewRadius(d.width/5); + this.lensGraphicsDecorator = new MagnifyIconGraphics(lensTransformer); + } + + public void activate() { + lensTransformer.setDelegate(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)); + if(lens == null) { + lens = new Lens(lensTransformer); + } + if(lensControls == null) { + lensControls = new LensControls(lensTransformer); + } + renderContext.setPickSupport(new ViewLensShapePickSupport(vv)); + lensTransformer.setDelegate(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.VIEW, lensTransformer); + this.renderContext.setGraphicsContext(lensGraphicsDecorator); + vv.getRenderer().setEdgeRenderer(reshapingEdgeRenderer); + vv.addPreRenderPaintable(lens); + vv.addPostRenderPaintable(lensControls); + vv.setGraphMouse(lensGraphMouse); + vv.setToolTipText(instructions); + vv.repaint(); + } + + public void deactivate() { + renderContext.setPickSupport(pickSupport); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.VIEW, lensTransformer.getDelegate()); + vv.removePreRenderPaintable(lens); + vv.removePostRenderPaintable(lensControls); + this.renderContext.setGraphicsContext(savedGraphicsDecorator); + vv.getRenderer().setEdgeRenderer(savedEdgeRenderer); + vv.setToolTipText(defaultToolTipText); + vv.setGraphMouse(graphMouse); + vv.repaint(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/MagnifyShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Component; +import java.awt.Shape; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +import edu.uci.ics.jung.algorithms.layout.PolarPoint; +import edu.uci.ics.jung.visualization.transform.MagnifyTransformer; +import edu.uci.ics.jung.visualization.transform.MutableTransformer; + +/** + * MagnifyShapeTransformer extends MagnifyTransformer and + * adds implementations for methods in ShapeTransformer. + * It modifies the shapes (Vertex, Edge, and Arrowheads) so that + * they are enlarged by the magnify transformation. + * + * @author Tom Nelson + */ +public class MagnifyShapeTransformer extends MagnifyTransformer + implements ShapeFlatnessTransformer { + + /** + * Create an instance, setting values from the passed component + * and registering to listen for size changes on the component. + * + * @param component the component used for rendering + */ + public MagnifyShapeTransformer(Component component) { + this(component, null); + } + + /** + * Create an instance, setting values from the passed component + * and registering to listen for size changes on the component, + * with a possibly shared transform delegate. + * + * @param component the component used for rendering + * @param delegate the transformer to use + */ + public MagnifyShapeTransformer(Component component, MutableTransformer delegate) { + super(component, delegate); + } + + /** + * Transform the supplied shape with the overridden transform + * method so that the shape is distorted by the magnify + * transform. + * @param shape a shape to transform + * @return a GeneralPath for the transformed shape + */ + public Shape transform(Shape shape) { + return transform(shape, 0); + } + public Shape transform(Shape shape, float flatness) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + PathIterator iterator = null; + if(flatness == 0) { + iterator = shape.getPathIterator(null); + } else { + iterator = shape.getPathIterator(null, flatness); + } + for( ; + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = _transform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + Point2D q = _transform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = _transform(new Point2D.Float(coords[0], coords[1])); + q = _transform(new Point2D.Float(coords[2], coords[3])); + Point2D r = _transform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + + public Shape inverseTransform(Shape shape) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + for(PathIterator iterator=shape.getPathIterator(null); + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + Point2D q = _inverseTransform(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = _inverseTransform(new Point2D.Float(coords[0], coords[1])); + q = _inverseTransform(new Point2D.Float(coords[2], coords[3])); + Point2D r = _inverseTransform(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + + private Point2D _transform(Point2D graphPoint) { + if(graphPoint == null) return null; + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + // transform the point from the graph to the view + Point2D viewPoint = graphPoint; + // calculate point from center + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + double theta = polar.getTheta(); + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint; + + double mag = magnification; + radius *= mag; + + radius = Math.min(radius, viewRadius); + Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + + /** + * override base class to un-project the fisheye effect + */ + private Point2D _inverseTransform(Point2D viewPoint) { + + viewPoint = delegate.inverseTransform(viewPoint); + Point2D viewCenter = getViewCenter(); + double viewRadius = getViewRadius(); + double ratio = getRatio(); + double dx = viewPoint.getX() - viewCenter.getX(); + double dy = viewPoint.getY() - viewCenter.getY(); + // factor out ellipse + dx *= ratio; + + Point2D pointFromCenter = new Point2D.Double(dx, dy); + + PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter); + + double radius = polar.getRadius(); + if(radius > viewRadius) return viewPoint; + + double mag = magnification; + radius /= mag; + polar.setRadius(radius); + Point2D projectedPoint = PolarPoint.polarToCartesian(polar); + projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY()); + Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(), + projectedPoint.getY()+viewCenter.getY()); + return translatedBack; + } + + /** + * Magnify the shape, without considering the Lens. + * @param shape the shape to magnify + * @return the transformed shape + */ + public Shape magnify(Shape shape) { + return magnify(shape, 0); + } + public Shape magnify(Shape shape, float flatness) { + GeneralPath newPath = new GeneralPath(); + float[] coords = new float[6]; + PathIterator iterator = null; + if(flatness == 0) { + iterator = shape.getPathIterator(null); + } else { + iterator = shape.getPathIterator(null, flatness); + } + for( ; + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = magnify(new Point2D.Float(coords[0], coords[1])); + newPath.moveTo((float)p.getX(), (float)p.getY()); + break; + + case PathIterator.SEG_LINETO: + p = magnify(new Point2D.Float(coords[0], coords[1])); + newPath.lineTo((float)p.getX(), (float) p.getY()); + break; + + case PathIterator.SEG_QUADTO: + p = magnify(new Point2D.Float(coords[0], coords[1])); + Point2D q = magnify(new Point2D.Float(coords[2], coords[3])); + newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY()); + break; + + case PathIterator.SEG_CUBICTO: + p = magnify(new Point2D.Float(coords[0], coords[1])); + q = magnify(new Point2D.Float(coords[2], coords[3])); + Point2D r = magnify(new Point2D.Float(coords[4], coords[5])); + newPath.curveTo((float)p.getX(), (float)p.getY(), + (float)q.getX(), (float)q.getY(), + (float)r.getX(), (float)r.getY()); + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + break; + + } + } + return newPath; + } + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/package.html libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/package.html --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/package.html 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/package.html 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,19 @@ + + + + + + + +

        Visualization mechanisms related to transformation of graph element shapes. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeFlatnessTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeFlatnessTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeFlatnessTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeFlatnessTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 16, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Shape; + +/** + * Provides methods to map points from one coordinate system to + * another: graph to screen and screen to graph. + * The flatness parameter is used to break a curved shape into + * smaller segments in order to perform a more detailed + * transformation. + * + * @author Tom Nelson + */ +public interface ShapeFlatnessTransformer extends ShapeTransformer { + + /** + * map a shape from graph coordinate system to the + * screen coordinate system + * @param shape the shape to be transformed + * @param flatness used to break the supplied shape into segments + * @return a GeneralPath (Shape) representing the screen points of the shape + */ + Shape transform(Shape shape, float flatness); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeTransformer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeTransformer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeTransformer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ShapeTransformer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Apr 16, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Shape; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; + +/** + * Provides methods to map points from one coordinate system to + * another: graph to screen and screen to graph. + * + * @author Tom Nelson + */ +public interface ShapeTransformer extends BidirectionalTransformer { + + /** + * map a shape from graph coordinate system to the + * screen coordinate system + * @param shape the Shape to transform + * @return a GeneralPath (Shape) representing the screen points of the shape + */ + Shape transform(Shape shape); + + Shape inverseTransform(Shape shape); +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingFlatnessGraphics.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingFlatnessGraphics.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingFlatnessGraphics.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingFlatnessGraphics.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 11, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Graphics2D; +import java.awt.Shape; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; +import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer; + + +/** + * subclassed to pass certain operations thru the Function + * before the base class method is applied + * This is useful when you want to apply non-affine transformations + * to the Graphics2D used to draw elements of the graph. + * + * @author Tom Nelson + * + * + */ +public class TransformingFlatnessGraphics extends TransformingGraphics { + + float flatness = 0; + + public TransformingFlatnessGraphics(BidirectionalTransformer transformer) { + this(transformer, null); + } + + public TransformingFlatnessGraphics(BidirectionalTransformer transformer, Graphics2D delegate) { + super(transformer, delegate); + } + + public void draw(Shape s, float flatness) { + Shape shape = null; + if(transformer instanceof ShapeFlatnessTransformer) { + shape = ((ShapeFlatnessTransformer)transformer).transform(s, flatness); + } else { + shape = ((ShapeTransformer)transformer).transform(s); + } + delegate.draw(shape); + + } + + public void fill(Shape s, float flatness) { + Shape shape = null; + if(transformer instanceof HyperbolicTransformer) { + shape = ((HyperbolicShapeTransformer)transformer).transform(s, flatness); + } else { + shape = ((ShapeTransformer)transformer).transform(s); + } + delegate.fill(shape); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingGraphics.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingGraphics.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingGraphics.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/TransformingGraphics.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 11, 2005 + */ + +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.ImageObserver; + +import edu.uci.ics.jung.visualization.transform.BidirectionalTransformer; + + +/** + * subclassed to pass certain operations thru the Function + * before the base class method is applied + * This is useful when you want to apply non-affine transformations + * to the Graphics2D used to draw elements of the graph. + * + * @author Tom Nelson + * + * + */ +public class TransformingGraphics extends GraphicsDecorator { + + /** + * the Function to apply + */ + protected BidirectionalTransformer transformer; + + public TransformingGraphics(BidirectionalTransformer transformer) { + this(transformer, null); + } + + public TransformingGraphics(BidirectionalTransformer Function, Graphics2D delegate) { + super(delegate); + this.transformer = Function; + } + + /** + * @return Returns the Function. + */ + public BidirectionalTransformer getTransformer() { + return transformer; + } + + /** + * @param Function The Function to set. + */ + public void setTransformer(BidirectionalTransformer Function) { + this.transformer = Function; + } + + /** + * transform the shape before letting the delegate draw it + */ + public void draw(Shape s) { + Shape shape = ((ShapeTransformer)transformer).transform(s); + delegate.draw(shape); + } + + public void draw(Shape s, float flatness) { + Shape shape = null; + if(transformer instanceof ShapeFlatnessTransformer) { + shape = ((ShapeFlatnessTransformer)transformer).transform(s, flatness); + } else { + shape = ((ShapeTransformer)transformer).transform(s); + } + delegate.draw(shape); + + } + + /** + * transform the shape before letting the delegate fill it + */ + public void fill(Shape s) { + Shape shape = ((ShapeTransformer)transformer).transform(s); + delegate.fill(shape); + } + + public void fill(Shape s, float flatness) { + Shape shape = null; + if(transformer instanceof ShapeFlatnessTransformer) { + shape = ((ShapeFlatnessTransformer)transformer).transform(s, flatness); + } else { + shape = ((ShapeTransformer)transformer).transform(s); + } + delegate.fill(shape); + } + + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + Image image = null; + if(transformer instanceof ShapeFlatnessTransformer) { + Rectangle2D r = new Rectangle2D.Double(x,y,img.getWidth(observer),img.getHeight(observer)); + Rectangle2D s = ((ShapeTransformer)transformer).transform(r).getBounds2D(); + image = img.getScaledInstance((int)s.getWidth(), (int)s.getHeight(), Image.SCALE_SMOOTH); + x = (int) s.getMinX(); + y = (int) s.getMinY(); + } else { + image = img; + } + return delegate.drawImage(image, x, y, observer); + } + + public boolean drawImage(Image img, AffineTransform at, ImageObserver observer) { + Image image = null; + int x = (int)at.getTranslateX(); + int y = (int)at.getTranslateY(); + if(transformer instanceof ShapeFlatnessTransformer) { + Rectangle2D r = new Rectangle2D.Double(x,y,img.getWidth(observer),img.getHeight(observer)); + Rectangle2D s = ((ShapeTransformer)transformer).transform(r).getBounds2D(); + image = img.getScaledInstance((int)s.getWidth(), (int)s.getHeight(), Image.SCALE_SMOOTH); + x = (int) s.getMinX(); + y = (int) s.getMinY(); + at.setToTranslation(s.getMinX(), s.getMinY()); + } else { + image = img; + } + return delegate.drawImage(image, at, observer); + } + + /** + * transform the shape before letting the delegate apply 'hit' + * with it + */ + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + Shape shape = ((ShapeTransformer)transformer).transform(s); + return delegate.hit(rect, shape, onStroke); + } + + public Graphics create() { + return delegate.create(); + } + + public void dispose() { + delegate.dispose(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ViewLensSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ViewLensSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ViewLensSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/transform/shape/ViewLensSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.transform.shape; + +import java.awt.Dimension; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.visualization.Layer; +import edu.uci.ics.jung.visualization.RenderContext; +import edu.uci.ics.jung.visualization.VisualizationViewer; +import edu.uci.ics.jung.visualization.control.ModalGraphMouse; +import edu.uci.ics.jung.visualization.picking.ViewLensShapePickSupport; +import edu.uci.ics.jung.visualization.renderers.Renderer; +import edu.uci.ics.jung.visualization.renderers.ReshapingEdgeRenderer; +import edu.uci.ics.jung.visualization.transform.AbstractLensSupport; +import edu.uci.ics.jung.visualization.transform.LensSupport; +import edu.uci.ics.jung.visualization.transform.LensTransformer; + +/** + * Uses a LensTransformer to use in the view + * transform. This one will distort Vertex shapes. + * + * @author Tom Nelson + * + * + */ +public class ViewLensSupport extends AbstractLensSupport + implements LensSupport { + + protected RenderContext renderContext; + protected GraphicsDecorator lensGraphicsDecorator; + protected GraphicsDecorator savedGraphicsDecorator; + protected GraphElementAccessor pickSupport; + protected Renderer.Edge savedEdgeRenderer; + protected Renderer.Edge reshapingEdgeRenderer; + + public ViewLensSupport(VisualizationViewer vv, + LensTransformer lensTransformer, + ModalGraphMouse lensGraphMouse) { + super(vv, lensGraphMouse); + this.renderContext = vv.getRenderContext(); + this.pickSupport = renderContext.getPickSupport(); + this.savedGraphicsDecorator = renderContext.getGraphicsContext(); + this.lensTransformer = lensTransformer; + Dimension d = vv.getSize(); + lensTransformer.setViewRadius(d.width/5); + this.lensGraphicsDecorator = new TransformingFlatnessGraphics(lensTransformer); + this.savedEdgeRenderer = vv.getRenderer().getEdgeRenderer(); + this.reshapingEdgeRenderer = new ReshapingEdgeRenderer(); + this.reshapingEdgeRenderer.setEdgeArrowRenderingSupport(savedEdgeRenderer.getEdgeArrowRenderingSupport()); + + } + public void activate() { + lensTransformer.setDelegate(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)); + if(lens == null) { + lens = new Lens(lensTransformer); + } + if(lensControls == null) { + lensControls = new LensControls(lensTransformer); + } + renderContext.setPickSupport(new ViewLensShapePickSupport(vv)); + lensTransformer.setDelegate(vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.VIEW, lensTransformer); + this.renderContext.setGraphicsContext(lensGraphicsDecorator); + vv.getRenderer().setEdgeRenderer(reshapingEdgeRenderer); + vv.prependPreRenderPaintable(lens); + vv.addPostRenderPaintable(lensControls); + vv.setGraphMouse(lensGraphMouse); + vv.setToolTipText(instructions); + vv.repaint(); + } + + public void deactivate() { +// savedViewTransformer.setTransform(lensTransformer.getDelegate().getTransform()); +// vv.setViewTransformer(savedViewTransformer); + renderContext.setPickSupport(pickSupport); + vv.getRenderContext().getMultiLayerTransformer().setTransformer(Layer.VIEW, lensTransformer.getDelegate()); + vv.removePreRenderPaintable(lens); + vv.removePostRenderPaintable(lensControls); + this.renderContext.setGraphicsContext(savedGraphicsDecorator); + vv.setRenderContext(renderContext); + vv.setToolTipText(defaultToolTipText); + vv.setGraphMouse(graphMouse); + vv.getRenderer().setEdgeRenderer(savedEdgeRenderer); + vv.repaint(); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Animator.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Animator.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Animator.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Animator.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.util; + +import edu.uci.ics.jung.algorithms.util.IterativeContext; + +/** + * + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class Animator implements Runnable { + + protected IterativeContext process; + protected boolean stop; + protected Thread thread; + + /** + * how long the relaxer thread pauses between iteration loops. + */ + protected long sleepTime = 10L; + + + public Animator(IterativeContext process) { + this(process, 10L); + } + + public Animator(IterativeContext process, long sleepTime) { + this.process = process; + this.sleepTime = sleepTime; + } + + /** + * @return the relaxer thread sleep time + */ + public long getSleepTime() { + return sleepTime; + } + + /** + * @param sleepTime the relaxer thread sleep time to set + */ + public void setSleepTime(long sleepTime) { + this.sleepTime = sleepTime; + } + + public void start() { + // in case its running + stop(); + stop = false; + thread = new Thread(this); + thread.setPriority(Thread.MIN_PRIORITY); + thread.start(); + } + + public synchronized void stop() { + stop = true; + } + + public void run() { + while (!process.done() && !stop) { + + process.step(); + + if (stop) + return; + + try { + Thread.sleep(sleepTime); + } catch (InterruptedException ie) { + } + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ArrowFactory.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ArrowFactory.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ArrowFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ArrowFactory.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * Created on Oct 19, 2004 + * + * Copyright (c) 2004, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.util; + +import java.awt.geom.GeneralPath; + +/** + * A utility class for creating arrowhead shapes. + * + * @author Joshua O'Madadhain + */ +public class ArrowFactory +{ + /** + * Returns an arrowhead in the shape of a simple isosceles triangle + * with the specified base and height measurements. It is placed + * with the vertical axis along the negative x-axis, with its base + * centered on (0,0). + * + * @param base the width of the arrow's base + * @param height the arrow's height + * @return a path in the form of an isosceles triangle with dimensions {@code (base, height)} + */ + public static GeneralPath getWedgeArrow(float base, float height) + { + GeneralPath arrow = new GeneralPath(); + arrow.moveTo(0,0); + arrow.lineTo( - height, base/2.0f); + arrow.lineTo( - height, -base/2.0f); + arrow.lineTo( 0, 0 ); + return arrow; + } + + /** + * Returns an arrowhead in the shape of an isosceles triangle + * with an isoceles-triangle notch taken out of the base, + * with the specified base and height measurements. It is placed + * with the vertical axis along the negative x-axis, with its base + * centered on (0,0). + * + * @param base the width of the arrow's base + * @param height the arrow's height + * @param notch_height the height of the arrow's notch + * @return a path in the form of a notched isosceles triangle + */ + public static GeneralPath getNotchedArrow(float base, float height, float notch_height) + { + GeneralPath arrow = new GeneralPath(); + arrow.moveTo(0,0); + arrow.lineTo(-height, base/2.0f); + arrow.lineTo(-(height - notch_height), 0); + arrow.lineTo(-height, -base/2.0f); + arrow.lineTo(0,0); + return arrow; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Caching.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Caching.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Caching.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/Caching.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * + */ +package edu.uci.ics.jung.visualization.util; + +/** + * Interface to provide external controls to an + * implementing class that manages a cache. + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public interface Caching { + + /** + * ititialize resources for a cache + * + */ + void init(); + + /** + * clear cache + * + */ + void clear(); + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ChangeEventSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ChangeEventSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ChangeEventSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ChangeEventSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 18, 2005 + */ + +package edu.uci.ics.jung.visualization.util; + +import javax.swing.event.ChangeListener; + +/** + * the implementing class provides support for ChangeEvents. + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public interface ChangeEventSupport { + + void addChangeListener(ChangeListener l); + + /** + * Removes a ChangeListener. + * @param l the listener to be removed + */ + void removeChangeListener(ChangeListener l); + + /** + * Returns an array of all the ChangeListeners added + * with addChangeListener(). + * + * @return all of the ChangeListeners added or an empty + * array if no listeners have been added + */ + ChangeListener[] getChangeListeners(); + + void fireStateChanged(); + +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/DefaultChangeEventSupport.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/DefaultChangeEventSupport.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/DefaultChangeEventSupport.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/DefaultChangeEventSupport.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Aug 18, 2005 + */ + +package edu.uci.ics.jung.visualization.util; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +/** + * Basic implementation of ChangeEventSupport, using + * standard jdk classes + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class DefaultChangeEventSupport implements ChangeEventSupport { + + Object eventSource; + /** + * holds the registered listeners + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Only one ChangeEvent is needed + * instance since the + * event's only state is the source property. The source of events + * generated is always "this". + */ + protected transient ChangeEvent changeEvent; + + public DefaultChangeEventSupport(Object eventSource) { + this.eventSource = eventSource; + } + + public void addChangeListener(ChangeListener l) { + listenerList.add(ChangeListener.class, l); + } + + public void removeChangeListener(ChangeListener l) { + listenerList.remove(ChangeListener.class, l); + } + + public ChangeListener[] getChangeListeners() { + return listenerList.getListeners(ChangeListener.class); + } + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * The primary listeners will be views that need to be repainted + * because of changes in this model instance + * @see EventListenerList + */ + public void fireStateChanged() { + // Guaranteed to return a non-null array + Object[] listeners = listenerList.getListenerList(); + // Process the listeners last to first, notifying + // those that are interested in this event + for (int i = listeners.length-2; i>=0; i-=2) { + if (listeners[i]==ChangeListener.class) { + // Lazily create the event: + if (changeEvent == null) + changeEvent = new ChangeEvent(eventSource); + ((ChangeListener)listeners[i+1]).stateChanged(changeEvent); + } + } + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/GeneralPathAsString.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/GeneralPathAsString.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/GeneralPathAsString.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/GeneralPathAsString.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,51 @@ +package edu.uci.ics.jung.visualization.util; + +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; + +public class GeneralPathAsString { + + public static String toString(GeneralPath newPath) { + StringBuilder sb = new StringBuilder(); + float[] coords = new float[6]; + for(PathIterator iterator=newPath.getPathIterator(null); + iterator.isDone() == false; + iterator.next()) { + int type = iterator.currentSegment(coords); + switch(type) { + case PathIterator.SEG_MOVETO: + Point2D p = new Point2D.Float(coords[0], coords[1]); + sb.append("moveTo "+p+"--"); + break; + + case PathIterator.SEG_LINETO: + p = new Point2D.Float(coords[0], coords[1]); + sb.append("lineTo "+p+"--"); + break; + + case PathIterator.SEG_QUADTO: + p = new Point2D.Float(coords[0], coords[1]); + Point2D q = new Point2D.Float(coords[2], coords[3]); + sb.append("quadTo "+p+" controlled by "+q); + break; + + case PathIterator.SEG_CUBICTO: + p = new Point2D.Float(coords[0], coords[1]); + q = new Point2D.Float(coords[2], coords[3]); + Point2D r = new Point2D.Float(coords[4], coords[5]); + sb.append("cubeTo "+p+" controlled by "+q+","+r); + + break; + + case PathIterator.SEG_CLOSE: + newPath.closePath(); + sb.append("close"); + break; + + } + } + return sb.toString(); + } + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ImageShapeUtils.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ImageShapeUtils.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ImageShapeUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/ImageShapeUtils.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Nov 7, 2015 + */ + +package edu.uci.ics.jung.visualization.util; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import edu.uci.ics.jung.visualization.FourPassImageShaper; + +public class ImageShapeUtils { + + /** + * Given the fileName of an image, possibly with a transparent + * background, return the Shape of the opaque part of the image + * @param fileName name of the image, loaded from the classpath + * @return the Shape + */ + public static Shape getShape(String fileName) { + return getShape(fileName, Integer.MAX_VALUE); + } + + /** + * Given the fileName of an image, possibly with a transparent + * background, return the Shape of the opaque part of the image + * @param fileName name of the image, loaded from the classpath + * @param max the maximum dimension of the traced shape + * @return the Shape + * + * @see #getShape(Image, int) + */ + public static Shape getShape(String fileName, int max) { + BufferedImage image = null; + try { + image = ImageIO.read(ImageShapeUtils.class.getResource(fileName)); + } catch(IOException ex) { + ex.printStackTrace(); + } + return getShape(image, max); + } + + /** + * Given an image, possibly with a transparent background, return + * the Shape of the opaque part of the image + * @param image the image whose shape is to be returned + * @return the Shape + */ + public static Shape getShape(Image image) { + return getShape(image, Integer.MAX_VALUE); + } + public static Shape getShape(Image image, int max) { + BufferedImage bi = + new BufferedImage(image.getWidth(null), image.getHeight(null), + BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.createGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + return getShape(bi, max); + } + + /** + * Given an image, possibly with a transparent background, return + * the Shape of the opaque part of the image + * + * If the image is larger than max in either direction, scale the + * image down to max-by-max, do the trace (on fewer points) then + * scale the resulting shape back up to the size of the original + * image. + * + * @param image the image to trace + * @param max used to restrict number of points in the resulting shape + * @return the Shape + */ + public static Shape getShape(BufferedImage image, int max) { + float width = image.getWidth(); + float height = image.getHeight(); + if(width > max || height > max) { + BufferedImage smaller = + new BufferedImage(max, max, BufferedImage.TYPE_INT_ARGB); + Graphics g = smaller.createGraphics(); + AffineTransform at = AffineTransform.getScaleInstance(max/width,max/height); + AffineTransform back = AffineTransform.getScaleInstance(width/max,height/max); + Graphics2D g2 = (Graphics2D)g; + g2.drawImage(image, at, null); + g2.dispose(); + return back.createTransformedShape(getShape(smaller)); + } else { + return FourPassImageShaper.getShape(image); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/LabelWrapper.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/LabelWrapper.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/LabelWrapper.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/LabelWrapper.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + */ +package edu.uci.ics.jung.visualization.util; + +import com.google.common.base.Function; + +/** + * A utility to wrap long lines, creating html strings + * with line breaks at a settable max line length + * + * @author Tom Nelson - tomnelson@dev.java.net + * + */ +public class LabelWrapper implements Function { + + int lineLength; + public static final String breaker = "

        "; + + /** + * Create an instance with default line break length = 10 + * + */ + public LabelWrapper() { + this(10); + } + + /** + * Create an instance with passed line break length + * @param lineLength the max length for lines + */ + public LabelWrapper(int lineLength) { + this.lineLength = lineLength; + } + + /** + * call 'wrap' to transform the passed String + */ + public String apply(String str) { + if(str != null) { + return wrap(str); + } else { + return null; + } + } + + /** + * line-wrap the passed String as an html string with + * break Strings inserted. + * + * @param str + * @return + */ + private String wrap(String str) { + StringBuilder buf = new StringBuilder(str); + int len = lineLength; + while(len < buf.length()) { + int idx = buf.lastIndexOf(" ", len); + if(idx != -1) { + buf.replace(idx, idx+1, breaker); + len = idx + breaker.length() +lineLength; + } else { + buf.insert(len, breaker); + len += breaker.length() + lineLength; + } + } + buf.insert(0, ""); + return buf.toString(); + } + + public static void main(String[] args) { + String[] lines = { + "This is a line with many short words that I will break into shorter lines.", + "thisisalinewithnobreakssowhoknowswhereitwillwrap", + "short line" + }; + LabelWrapper w = new LabelWrapper(10); + for(int i=0; i + + + + + + +

        Utilities for graph visualization. + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/PredicatedParallelEdgeIndexFunction.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/PredicatedParallelEdgeIndexFunction.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/PredicatedParallelEdgeIndexFunction.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/PredicatedParallelEdgeIndexFunction.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * Created on Sep 24, 2005 + * + * Copyright (c) 2005, The JUNG Authors + * + * All rights reserved. + * + * This software is open-source under the BSD license; see either + * "license.txt" or + * https://github.com/jrtom/jung/blob/master/LICENSE for a description. + */ +package edu.uci.ics.jung.visualization.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; + +import com.google.common.base.Predicate; + +import edu.uci.ics.jung.graph.Graph; +import edu.uci.ics.jung.graph.util.EdgeIndexFunction; +import edu.uci.ics.jung.graph.util.Pair; + +/** + * A class which creates and maintains indices for parallel edges. + * Edges are evaluated by a Predicate function and those that + * evaluate to true are excluded from computing a parallel offset + * + * @author Tom Nelson + * + */ +public class PredicatedParallelEdgeIndexFunction implements EdgeIndexFunction { + protected Map edge_index = new HashMap(); + protected Predicate predicate; + + /** + * @param graph the graph with respect to which the index is calculated + */ + private PredicatedParallelEdgeIndexFunction() { + } + + public static PredicatedParallelEdgeIndexFunction getInstance() { + return new PredicatedParallelEdgeIndexFunction(); + } + + /** + * Returns the index for the specified edge. + * Calculates the indices for e and for all edges parallel + * to e. + * @param graph the graph with respect to which the index is calculated + * @param e the edge whose index is to be calculated + * + * @return the index of the edge with respect to this index function + */ + public int getIndex(Graph graph, E e) { + + if(predicate.apply(e)) { + return 0; + } + Integer index = edge_index.get(e); + if(index == null) { + Pair endpoints = graph.getEndpoints(e); + V u = endpoints.getFirst(); + V v = endpoints.getSecond(); + if(u.equals(v)) { + index = getIndex(graph, e, v); + } else { + index = getIndex(graph, e, u, v); + } + } + return index.intValue(); + } + + protected int getIndex(Graph graph, E e, V v, V u) { + Collection commonEdgeSet = new HashSet(graph.getIncidentEdges(u)); + commonEdgeSet.retainAll(graph.getIncidentEdges(v)); + for(Iterator iterator=commonEdgeSet.iterator(); iterator.hasNext(); ) { + E edge = iterator.next(); + Pair ep = graph.getEndpoints(edge); + V first = ep.getFirst(); + V second = ep.getSecond(); + // remove loops + if(first.equals(second) == true) { + iterator.remove(); + } + // remove edges in opposite direction + if(first.equals(v) == false) { + iterator.remove(); + } + } + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(other, count); + count++; + } + } + edge_index.put(e, count); + return count; + } + + protected int getIndex(Graph graph, E e, V v) { + Collection commonEdgeSet = new HashSet(); + for(E another : graph.getIncidentEdges(v)) { + V u = graph.getOpposite(v, another); + if(u.equals(v)) { + commonEdgeSet.add(another); + } + } + int count=0; + for(E other : commonEdgeSet) { + if(e.equals(other) == false) { + edge_index.put(other, count); + count++; + } + } + edge_index.put(e, count); + return count; + } + + public Predicate getPredicate() { + return predicate; + } + + public void setPredicate(Predicate predicate) { + this.predicate = predicate; + } + + /** + * Resets the indices for this edge and its parallel edges. + * Should be invoked when an edge parallel to e + * has been added or removed in this graph. + * @param graph the graph with respect to which the index is calculated + * @param e the edge whose indices are to be reset for {@code graph} + */ + public void reset(Graph graph, E e) { + Pair endpoints = graph.getEndpoints(e); + getIndex(graph, e, endpoints.getFirst()); + getIndex(graph, e, endpoints.getFirst(), endpoints.getSecond()); + } + + /** + * Clears all edge indices for all edges in all graphs. + * Does not recalculate the indices. + */ + public void reset() + { + edge_index.clear(); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/VertexShapeFactory.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/VertexShapeFactory.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/VertexShapeFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/util/VertexShapeFactory.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2003, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on Jul 20, 2004 + */ +package edu.uci.ics.jung.visualization.util; + +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import com.google.common.base.Function; +import com.google.common.base.Functions; + +/** + * A utility class for generating Shapes for drawing vertices. + * The available shapes include rectangles, rounded rectangles, ellipses, + * regular polygons, and regular stars. The dimensions of the requested + * shapes are defined by the specified vertex size function (specified by + * a {@code Function}) and vertex aspect ratio function + * (specified by a {@code Function}) implementations: the width + * of the bounding box of the shape is given by the vertex size, and the + * height is given by the size multiplied by the vertex's aspect ratio. + * + * @author Joshua O'Madadhain + */ +public class VertexShapeFactory +{ + protected Function vsf; + protected Function varf; + + /** + * Creates an instance with the specified vertex size and aspect ratio functions. + * + * @param vsf provides a size (width) for each vertex + * @param varf provides a height/width ratio for each vertex + */ + public VertexShapeFactory(Function vsf, Function varf) + { + this.vsf = vsf; + this.varf = varf; + } + + /** + * Creates a VertexShapeFactory with a constant size of + * 10 and a constant aspect ratio of 1. + */ + public VertexShapeFactory() + { + this(Functions.constant(10), + Functions.constant(1.0f)); + } + + private static final Rectangle2D theRectangle = new Rectangle2D.Float(); + + /** + * Returns a Rectangle2D whose width and + * height are defined by this instance's size and + * aspect ratio functions for this vertex. + * + * @param v the vertex for which the shape will be drawn + * @return a rectangle for this vertex + */ + public Rectangle2D getRectangle(V v) + { + float width = vsf.apply(v); + float height = width * varf.apply(v); + float h_offset = -(width / 2); + float v_offset = -(height / 2); + theRectangle.setFrame(h_offset, v_offset, width, height); + return theRectangle; + } + + private static final Ellipse2D theEllipse = new Ellipse2D.Float(); + + /** + * Returns a Ellipse2D whose width and + * height are defined by this instance's size and + * aspect ratio functions for this vertex. + * + * @param v the vertex for which the shape will be drawn + * @return an ellipse for this vertex + */ + public Ellipse2D getEllipse(V v) + { + theEllipse.setFrame(getRectangle(v)); + return theEllipse; + } + + private static final RoundRectangle2D theRoundRectangle = + new RoundRectangle2D.Float(); + /** + * Returns a RoundRectangle2D whose width and + * height are defined by this instance's size and + * aspect ratio functions for this vertex. The arc size is + * set to be half the minimum of the height and width of the frame. + * + * @param v the vertex for which the shape will be drawn + * @return an round rectangle for this vertex + */ + public RoundRectangle2D getRoundRectangle(V v) + { + Rectangle2D frame = getRectangle(v); + float arc_size = (float)Math.min(frame.getHeight(), frame.getWidth()) / 2; + theRoundRectangle.setRoundRect(frame.getX(), frame.getY(), + frame.getWidth(), frame.getHeight(), arc_size, arc_size); + return theRoundRectangle; + } + + private static final GeneralPath thePolygon = new GeneralPath(); + + /** + * Returns a regular num_sides-sided + * Polygon whose bounding + * box's width and height are defined by this instance's size and + * aspect ratio functions for this vertex. + * + * @param v the vertex for which the shape will be drawn + * @param num_sides the number of sides of the polygon; must be ≥ 3. + * @return a regular polygon for this vertex + */ + public Shape getRegularPolygon(V v, int num_sides) + { + if (num_sides < 3) + throw new IllegalArgumentException("Number of sides must be >= 3"); + Rectangle2D frame = getRectangle(v); + float width = (float)frame.getWidth(); + float height = (float)frame.getHeight(); + + // generate coordinates + double angle = 0; + thePolygon.reset(); + thePolygon.moveTo(0,0); + thePolygon.lineTo(width, 0); + double theta = (2 * Math.PI) / num_sides; + for (int i = 2; i < num_sides; i++) + { + angle -= theta; + float delta_x = (float) (width * Math.cos(angle)); + float delta_y = (float) (width * Math.sin(angle)); + Point2D prev = thePolygon.getCurrentPoint(); + thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); + } + thePolygon.closePath(); + + // scale polygon to be right size, translate to center at (0,0) + Rectangle2D r = thePolygon.getBounds2D(); + double scale_x = width / r.getWidth(); + double scale_y = height / r.getHeight(); + float translationX = (float) (r.getMinX() + r.getWidth()/2); + float translationY = (float) (r.getMinY() + r.getHeight()/2); + + AffineTransform at = AffineTransform.getScaleInstance(scale_x, scale_y); + at.translate(-translationX, -translationY); + + Shape shape = at.createTransformedShape(thePolygon); + return shape; + } + + /** + * Returns a regular Polygon of num_points + * points whose bounding + * box's width and height are defined by this instance's size and + * aspect ratio functions for this vertex. + * + * @param v the vertex for which the shape will be drawn + * @param num_points the number of points of the polygon; must be ≥ 5. + * @return an star shape for this vertex + */ + public Shape getRegularStar(V v, int num_points) + { + if (num_points < 5) + throw new IllegalArgumentException("Number of sides must be >= 5"); + Rectangle2D frame = getRectangle(v); + float width = (float) frame.getWidth(); + float height = (float) frame.getHeight(); + + // generate coordinates + double theta = (2 * Math.PI) / num_points; + double angle = -theta/2; + thePolygon.reset(); + thePolygon.moveTo(0,0); + float delta_x = width * (float)Math.cos(angle); + float delta_y = width * (float)Math.sin(angle); + Point2D prev = thePolygon.getCurrentPoint(); + thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); + for (int i = 1; i < num_points; i++) + { + angle += theta; + delta_x = width * (float)Math.cos(angle); + delta_y = width * (float)Math.sin(angle); + prev = thePolygon.getCurrentPoint(); + thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); + angle -= theta*2; + delta_x = width * (float)Math.cos(angle); + delta_y = width * (float)Math.sin(angle); + prev = thePolygon.getCurrentPoint(); + thePolygon.lineTo((float)prev.getX() + delta_x, (float)prev.getY() + delta_y); + } + thePolygon.closePath(); + + // scale polygon to be right size, translate to center at (0,0) + Rectangle2D r = thePolygon.getBounds2D(); + double scale_x = width / r.getWidth(); + double scale_y = height / r.getHeight(); + + float translationX = (float) (r.getMinX() + r.getWidth()/2); + float translationY = (float) (r.getMinY() + r.getHeight()/2); + + AffineTransform at = AffineTransform.getScaleInstance(scale_x, scale_y); + at.translate(-translationX, -translationY); + + Shape shape = at.createTransformedShape(thePolygon); + return shape; + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationImageServer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationImageServer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationImageServer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationImageServer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; + +import edu.uci.ics.jung.algorithms.layout.Layout; + +/** + * A class that could be used on the server side of a thin-client application. It creates the jung + * visualization, then produces an image of it. + * @author tom + * + * @param the vertex type + * @param the edge type + */ +@SuppressWarnings("serial") +public class VisualizationImageServer extends BasicVisualizationServer { + + Map renderingHints = new HashMap(); + + /** + * Creates a new instance with the specified layout and preferred size. + * + * @param layout the Layout instance; provides the vertex locations + * @param preferredSize the preferred size of the image + */ + public VisualizationImageServer(Layout layout, Dimension preferredSize) { + super(layout, preferredSize); + setSize(preferredSize); + renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + addNotify(); + } + + public Image getImage(Point2D center, Dimension d) + { + int width = getWidth(); + int height = getHeight(); + + float scalex = (float)width/d.width; + float scaley = (float)height/d.height; + try + { + renderContext.getMultiLayerTransformer().getTransformer(Layer.VIEW).scale(scalex, scaley, center); + + BufferedImage bi = new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = bi.createGraphics(); + graphics.setRenderingHints(renderingHints); + paint(graphics); + graphics.dispose(); + return bi; + } finally { + renderContext.getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity(); + } + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationModel.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationModel.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationModel.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationModel.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2005, The JUNG Authors + * All rights reserved. + * + * This software is open-source under the BSD license; see either "license.txt" + * or https://github.com/jrtom/jung/blob/master/LICENSE for a description. + * + * Created on May 4, 2005 + */ + +package edu.uci.ics.jung.visualization; + +import java.awt.Dimension; + +import javax.swing.event.ChangeListener; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.algorithms.layout.util.Relaxer; +import edu.uci.ics.jung.visualization.util.ChangeEventSupport; + +/** + * Interface for the state holding model of the VisualizationViewer. + * Refactored and extracted from the 1.6.0 version of VisualizationViewer + * + * @author Tom Nelson + */ +public interface VisualizationModel extends ChangeEventSupport { + + Relaxer getRelaxer(); + + /** + * set the graph Layout + * @param layout the layout to use + */ + void setGraphLayout(Layout layout); + + /** + * Sets the graph Layout and initialize the Layout size to + * the passed dimensions. The passed Dimension will often be + * the size of the View that will display the graph. + * @param layout the layout to use + * @param d the dimensions to use + */ + void setGraphLayout(Layout layout, Dimension d); + + /** + * @return the current graph layout + */ + Layout getGraphLayout(); + + /** + * Register l as a listeners to changes in the model. The View registers + * in order to repaint itself when the model changes. + * @param l the listener to add + */ + void addChangeListener(ChangeListener l); + + /** + * Removes a ChangeListener. + * @param l the listener to be removed + */ + void removeChangeListener(ChangeListener l); + + /** + * Returns an array of all the ChangeListeners added + * with addChangeListener(). + * + * @return all of the ChangeListeners added or an empty + * array if no listeners have been added + */ + ChangeListener[] getChangeListeners(); +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationServer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationServer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationServer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationServer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,198 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization; + +import java.awt.Graphics; +import java.awt.RenderingHints.Key; +import java.awt.geom.Point2D; +import java.util.Map; + +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.EventListenerList; + +import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor; +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.picking.PickedState; +import edu.uci.ics.jung.visualization.renderers.Renderer; + +/** + * @author tom + * + * @param the vertex type + * @param the edge type + */ +public interface VisualizationServer { + + /** + * Specify whether this class uses its offscreen image or not. + * + * @param doubleBuffered if true, then doubleBuffering in the superclass is set to 'false' + */ + void setDoubleBuffered(boolean doubleBuffered); + + /** + * Returns whether this class uses double buffering. The superclass + * will be the opposite state. + * @return the double buffered state + */ + boolean isDoubleBuffered(); + + /** + * @return the model. + */ + VisualizationModel getModel(); + + /** + * @param model the model for this class to use + */ + void setModel(VisualizationModel model); + + /** + * In response to changes from the model, repaint the + * view, then fire an event to any listeners. + * Examples of listeners are the GraphZoomScrollPane and + * the BirdsEyeVisualizationViewer + * @param e the change event + */ + void stateChanged(ChangeEvent e); + + /** + * Sets the showing Renderer to be the input Renderer. Also + * tells the Renderer to refer to this instance + * as a PickedKey. (Because Renderers maintain a small + * amount of state, such as the PickedKey, it is important + * to create a separate instance for each VV instance.) + * @param r the renderer to use + */ + void setRenderer(Renderer r); + + /** + * @return the renderer used by this instance. + */ + Renderer getRenderer(); + + /** + * Replaces the current graph layout with {@code layout}. + * @param layout the new layout to set + */ + void setGraphLayout(Layout layout); + + /** + * @return the current graph layout. + */ + Layout getGraphLayout(); + + /** + * Makes the component visible if {@code aFlag} is true, or invisible if false. + * @param aFlag true iff the component should be visible + * @see javax.swing.JComponent#setVisible(boolean) + */ + void setVisible(boolean aFlag); + + /** + * @return the renderingHints + */ + Map getRenderingHints(); + + /** + * @param renderingHints The renderingHints to set. + */ + void setRenderingHints(Map renderingHints); + + /** + * @param paintable The paintable to add. + */ + void addPreRenderPaintable(Paintable paintable); + + /** + * @param paintable The paintable to remove. + */ + void removePreRenderPaintable(Paintable paintable); + + /** + * @param paintable The paintable to add. + */ + void addPostRenderPaintable(Paintable paintable); + + /** + * @param paintable The paintable to remove. + */ + void removePostRenderPaintable(Paintable paintable); + + /** + * Adds a ChangeListener. + * @param l the listener to be added + */ + void addChangeListener(ChangeListener l); + + /** + * Removes a ChangeListener. + * @param l the listener to be removed + */ + void removeChangeListener(ChangeListener l); + + /** + * Returns an array of all the ChangeListeners added + * with addChangeListener(). + * + * @return all of the ChangeListeners added or an empty + * array if no listeners have been added + */ + ChangeListener[] getChangeListeners(); + + /** + * Notifies all listeners that have registered interest for + * notification on this event type. The event instance + * is lazily created. + * @see EventListenerList + */ + void fireStateChanged(); + + /** + * @return the vertex PickedState instance + */ + PickedState getPickedVertexState(); + + /** + * @return the edge PickedState instance + */ + PickedState getPickedEdgeState(); + + void setPickedVertexState(PickedState pickedVertexState); + + void setPickedEdgeState(PickedState pickedEdgeState); + + /** + * @return the GraphElementAccessor + */ + GraphElementAccessor getPickSupport(); + + /** + * @param pickSupport The pickSupport to set. + */ + void setPickSupport(GraphElementAccessor pickSupport); + + Point2D getCenter(); + + RenderContext getRenderContext(); + + void setRenderContext(RenderContext renderContext); + + void repaint(); + + /** + * an interface for the preRender and postRender + */ + interface Paintable { + public void paint(Graphics g); + public boolean useTransform(); + } +} \ No newline at end of file diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationViewer.java libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationViewer.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationViewer.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/main/java/edu/uci/ics/jung/visualization/VisualizationViewer.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,191 @@ +/* +* Copyright (c) 2003, The JUNG Authors +* +* All rights reserved. +* +* This software is open-source under the BSD license; see either +* "license.txt" or +* https://github.com/jrtom/jung/blob/master/LICENSE for a description. +*/ +package edu.uci.ics.jung.visualization; + +import java.awt.Dimension; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelListener; +import java.awt.geom.Point2D; + +import javax.swing.ToolTipManager; + +import com.google.common.base.Function; + +import edu.uci.ics.jung.algorithms.layout.Layout; +import edu.uci.ics.jung.visualization.control.GraphMouseListener; +import edu.uci.ics.jung.visualization.control.MouseListenerTranslator; + +/** + * Adds mouse behaviors and tooltips to the graph visualization base class + * + * @author Joshua O'Madadhain + * @author Tom Nelson + * @author Danyel Fisher + */ +@SuppressWarnings("serial") +public class VisualizationViewer extends BasicVisualizationServer { + + protected Function vertexToolTipTransformer; + protected Function edgeToolTipTransformer; + protected Function mouseEventToolTipTransformer; + + /** + * provides MouseListener, MouseMotionListener, and MouseWheelListener + * events to the graph + */ + protected GraphMouse graphMouse; + + protected MouseListener requestFocusListener = new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + requestFocusInWindow(); + } + }; + + + public VisualizationViewer(Layout layout) { + this(new DefaultVisualizationModel(layout)); + } + + public VisualizationViewer(Layout layout, Dimension preferredSize) { + this(new DefaultVisualizationModel(layout, preferredSize), preferredSize); + } + + public VisualizationViewer(VisualizationModel model) { + this(model, new Dimension(600,600)); + } + + public VisualizationViewer(VisualizationModel model, + Dimension preferredSize) { + super(model, preferredSize); + setFocusable(true); + addMouseListener(requestFocusListener); + } + + /** + * a setter for the GraphMouse. This will remove any + * previous GraphMouse (including the one that + * is added in the initMouseClicker method. + * @param graphMouse new value + */ + public void setGraphMouse(GraphMouse graphMouse) { + this.graphMouse = graphMouse; + MouseListener[] ml = getMouseListeners(); + for(int i=0; iGraphMouse + */ + public GraphMouse getGraphMouse() { + return graphMouse; + } + + /** + * This is the interface for adding a mouse listener. The GEL + * will be called back with mouse clicks on vertices. + * @param gel the mouse listener to add + */ + public void addGraphMouseListener( GraphMouseListener gel ) { + addMouseListener( new MouseListenerTranslator( gel, this )); + } + + /** + * Override to request focus on mouse enter, if a key listener is added + * @see java.awt.Component#addKeyListener(java.awt.event.KeyListener) + */ + @Override + public synchronized void addKeyListener(KeyListener l) { + super.addKeyListener(l); + } + + /** + * @param edgeToolTipTransformer the edgeToolTipTransformer to set + */ + public void setEdgeToolTipTransformer( + Function edgeToolTipTransformer) { + this.edgeToolTipTransformer = edgeToolTipTransformer; + ToolTipManager.sharedInstance().registerComponent(this); + } + + /** + * @param mouseEventToolTipTransformer the mouseEventToolTipTransformer to set + */ + public void setMouseEventToolTipTransformer( + Function mouseEventToolTipTransformer) { + this.mouseEventToolTipTransformer = mouseEventToolTipTransformer; + ToolTipManager.sharedInstance().registerComponent(this); + } + + /** + * @param vertexToolTipTransformer the vertexToolTipTransformer to set + */ + public void setVertexToolTipTransformer( + Function vertexToolTipTransformer) { + this.vertexToolTipTransformer = vertexToolTipTransformer; + ToolTipManager.sharedInstance().registerComponent(this); + } + + /** + * called by the superclass to display tooltips + */ + public String getToolTipText(MouseEvent event) { + Layout layout = getGraphLayout(); + Point2D p = null; + if(vertexToolTipTransformer != null) { + p = event.getPoint(); + //renderContext.getBasicTransformer().inverseViewTransform(event.getPoint()); + V vertex = getPickSupport().getVertex(layout, p.getX(), p.getY()); + if(vertex != null) { + return vertexToolTipTransformer.apply(vertex); + } + } + if(edgeToolTipTransformer != null) { + if(p == null) p = renderContext.getMultiLayerTransformer().inverseTransform(Layer.VIEW, event.getPoint()); + E edge = getPickSupport().getEdge(layout, p.getX(), p.getY()); + if(edge != null) { + return edgeToolTipTransformer.apply(edge); + } + } + if(mouseEventToolTipTransformer != null) { + return mouseEventToolTipTransformer.apply(event); + } + return super.getToolTipText(event); + } + + /** + * a convenience type to represent a class that + * processes all types of mouse events for the graph + */ + public interface GraphMouse extends MouseListener, MouseMotionListener, MouseWheelListener {} + +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/site/site.xml libjung-free-java-2.1.1/jung-visualization/src/site/site.xml --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/site/site.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/site/site.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,14 @@ + + + ${project.name} + + + + + +

        + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/BasicVisualizationServerTest.java libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/BasicVisualizationServerTest.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/BasicVisualizationServerTest.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/BasicVisualizationServerTest.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,23 @@ +package edu.uci.ics.jung.visualization; + +import edu.uci.ics.jung.algorithms.layout.CircleLayout; +import edu.uci.ics.jung.graph.SparseGraph; +import edu.uci.ics.jung.visualization.picking.PickedState; +import junit.framework.TestCase; + +public class BasicVisualizationServerTest extends TestCase { + + /* + * Previously, a bug was introduced where the RenderContext in BasicVisualizationServer was reassigned, resulting + * in data like pickedVertexState to be lost. + */ + public void testRenderContextNotOverridden() { + SparseGraph graph = new SparseGraph(); + CircleLayout layout = new CircleLayout(graph); + + BasicVisualizationServer server = new BasicVisualizationServer(layout); + + PickedState pickedVertexState = server.getRenderContext().getPickedVertexState(); + assertNotNull(pickedVertexState); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/control/TestCrossoverScalingControl.java libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/control/TestCrossoverScalingControl.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/control/TestCrossoverScalingControl.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/control/TestCrossoverScalingControl.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,76 @@ +package edu.uci.ics.jung.visualization.control; + +import java.awt.geom.Point2D; + +import junit.framework.TestCase; +import edu.uci.ics.jung.algorithms.layout.FRLayout; +import edu.uci.ics.jung.graph.SparseGraph; +import edu.uci.ics.jung.visualization.BasicVisualizationServer; +import edu.uci.ics.jung.visualization.VisualizationServer; + +public class TestCrossoverScalingControl extends TestCase { + + CrossoverScalingControl sc; + VisualizationServer vv; + + float crossover; + float scale; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public void setUp() { + sc = new CrossoverScalingControl(); + vv = new BasicVisualizationServer(new FRLayout(new SparseGraph())); + } + public void testCrossover() { + crossover = 2.0f; + scale = .5f; + sc.setCrossover(crossover); + sc.scale(vv, scale, new Point2D.Double()); +// System.err.println("crossover="+crossover); +// System.err.println("scale="+scale); +// System.err.println("layout scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale()); +// System.err.println("view scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale()); + } + public void testCrossover2() { + crossover = 2.0f; + scale = 1.5f; + sc.setCrossover(crossover); + sc.scale(vv, scale, new Point2D.Double()); +// System.err.println("crossover="+crossover); +// System.err.println("scale="+scale); +// System.err.println("layout scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale()); +// System.err.println("view scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale()); + + } + public void testCrossover3() { + crossover = 2.0f; + scale = 2.5f; + sc.setCrossover(crossover); + sc.scale(vv, scale, new Point2D.Double()); +// System.err.println("crossover="+crossover); +// System.err.println("scale="+scale); +// System.err.println("layout scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale()); +// System.err.println("view scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale()); + } + public void testCrossover4() { + crossover = 0.5f; + scale = 2.5f; + sc.setCrossover(crossover); + sc.scale(vv, scale, new Point2D.Double()); +// System.err.println("crossover="+crossover); +// System.err.println("scale="+scale); +// System.err.println("layout scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale()); +// System.err.println("view scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale()); + } + public void testCrossover5() { + crossover = 0.5f; + scale = .3f; + sc.setCrossover(crossover); + sc.scale(vv, scale, new Point2D.Double()); +// System.err.println("crossover="+crossover); +// System.err.println("scale="+scale); +// System.err.println("layout scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getScale()); +// System.err.println("view scale = "+vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getScale()); + } +} diff -Nru libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/TestImageShaper.java libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/TestImageShaper.java --- libjung-free-java-2.0.1+dfsg/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/TestImageShaper.java 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/jung-visualization/src/test/java/edu/uci/ics/jung/visualization/TestImageShaper.java 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,55 @@ +package edu.uci.ics.jung.visualization; + +import java.awt.Shape; +import java.awt.geom.PathIterator; +import java.awt.image.BufferedImage; + +import edu.uci.ics.jung.visualization.util.ImageShapeUtils; +import junit.framework.TestCase; + +public class TestImageShaper extends TestCase { + + BufferedImage image; + + @Override + protected void setUp() throws Exception { + super.setUp(); + int width = 6; + int height = 5; + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + for(int i=0; i = Regents of the University of California and the JUNG Project Authors + = University of California + = 2003 + +It allows redistribution of JUNG freely, albeit with acknowledgement of JUNG's being +a component in the redistributed software. +However, we would greatly appreciate it if you can let us know what you are doing with JUNG. + +-- +THE JUNG LICENSE + +Copyright (c) 2003-2015, Regents of the University of California and the JUNG Project Authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of JUNG, nor that of the University of California, nor the names of its + contributors, may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff -Nru libjung-free-java-2.0.1+dfsg/pom.xml libjung-free-java-2.1.1/pom.xml --- libjung-free-java-2.0.1+dfsg/pom.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/pom.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,264 @@ + + + 4.0.0 + net.sf.jung + jung-parent + 2.1.1 + pom + JUNG (parent metadata project) + http://jrtom.github.io/jung/ + + + The BSD License + https://github.com/jrtom/jung/blob/master/LICENSE + repo + + + + https://github.com/jrtom/jung + scm:git:git://github.com/jrtom/jung.git + scm:git:git://github.com/jrtom/jung.git + + + JUNG the Java Universal Network/Graph Framework--is a software + library that provides a common and extendible language for the + modeling, analysis, and visualization of data that can be + represented as a graph or network. It is written in Java, which + allows JUNG-based applications to make use of the extensive + built-in capabilities of the Java API, as well as those of other + existing third-party Java libraries. The JUNG architecture is + designed to support a variety of representations of entities and + their relations, such as directed and undirected graphs, + multi-modal graphs, graphs with parallel edges, and hypergraphs. + It provides a mechanism for annotating graphs, entities, and + relations with metadata. This facilitates the creation of + analytic tools for complex data sets that can examine the + relations between entities as well as the metadata attached to + each entity and relation. The current distribution of JUNG + includes implementations of a number of algorithms from graph + theory, data mining, and social network analysis, such as + routines for clustering, decomposition, optimization, random + graph generation, statistical analysis, and calculation of + network distances, flows, and importance measures (centrality, + PageRank, HITS, etc.). JUNG also provides a visualization + framework that makes it easy to construct tools for the + interactive exploration of network data. Users can use one of + the layout algorithms provided, or use the framework to create + their own custom layouts. In addition, filtering mechanisms are + provided which allow users to focus their attention, or their + algorithms, on specific portions of the graph. + + + jung-api + jung-graph-impl + jung-algorithms + jung-io + jung-visualization + jung-samples + + + 3.1.1 + + + UTF-8 + UTF-8 + 1.6 + + + 4.12 + 19.0 + + 2.7 + 3.5.1 + 1.6 + 2.6 + 2.10.4 + 2.5 + 3.6 + 2.5.3 + 2.19.1 + 3.0.1 + + + + eflat + Joshua + joshua.omadadhain+maven@gmail.com + https://sites.google.com/site/joshuaomadadhain + Google + http://www.google.com + -8 + + Owner + Developer + + + + offkey + Danyel + offkey@sf.net + Microsoft Research + http://research.microsoft.com + -8 + + Owner + Developer + + + + tomnelson + Tom + tomnelson@sf.net + ICCI + http://www.intergratedcc.com + -5 + + Developer + + + + + + + junit + junit + ${junit.version} + + + com.google.guava + guava + ${guava.version} + + + + + + + + maven-compiler-plugin + ${compiler.plugin.version} + + ${java.version} + ${java.version} + + + + maven-jar-plugin + ${jar.plugin.version} + + + + true + + + + + + maven-release-plugin + {release.plugin.version} + + forked-path + false + ${arguments} -Psonatype-oss-release + + + + + + + + + + maven-javadoc-plugin + ${javadoc.plugin.version} + + true + + http://docs.oracle.com/javaee/6/api/ + http://docs.oracle.com/javase/6/docs/api/ + + + + + maven-surefire-report-plugin + ${surefire.plugin.version} + + + org.codehaus.mojo + cobertura-maven-plugin + ${cobertura.plugin.version} + + + maven-pmd-plugin + ${pmd.plugin.version} + + ${java.version} + true + + + + maven-jxr-plugin + ${jxr.plugin.version} + + + + + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + + sonatype-nexus-staging + Nexus Release Repository + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + sonatype-oss-release + + + + maven-source-plugin + ${source.plugin.version} + + + attach-sources + + jar-no-fork + + + + + + maven-javadoc-plugin + ${javadoc.plugin.version} + + + attach-javadocs + + jar + + + + + + maven-gpg-plugin + ${gpg.plugin.version} + + + sign-artifacts + verify + + sign + + + + + + + + + diff -Nru libjung-free-java-2.0.1+dfsg/README.md libjung-free-java-2.1.1/README.md --- libjung-free-java-2.0.1+dfsg/README.md 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/README.md 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,52 @@ +## JUNG: The Java Universal Network/Graph Framework + +[![Build Status](https://travis-ci.org/jrtom/jung.svg?branch=master)](https://travis-ci.org/jrtom/jung) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.sf.jung/jung-algorithms/badge.svg)](https://maven-badges.herokuapp.com/maven-central/net.sf.jung/jung-algorithms) + +JUNG is a software library that provides a common and extendible language for the modeling, analysis, and visualization of +data that can be represented as a graph or network. Its basis in Java allows JUNG-based applications to make use of the +extensive built-in capabilities of the Java API, as well as those of other existing third-party Java libraries. + +[**JUNG Website**](http://jrtom.github.io/jung/) + +### Latest Release + +The most recent version of JUNG is [version 2.1](https://github.com/jrtom/jung/releases/tag/jung-2.1), released 18 March 2016. +* [Javadoc](http://jrtom.github.io/jung/javadoc/index.html) +* [Maven Search Repository](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22net.sf.jung%22%20AND%20v%3A%222.1%22%20AND%20(a%3A%22jung-api%22%20OR%20a%3A%22jung-graph-impl%22%20OR%20a%3A%22jung-visualization%22%20OR%20a%3A%22jung-algorithms%22%20OR%20a%3A%22jung-samples%22%20OR%20a%3A%22jung-io%22)) + * `jung-api`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-api/2.1/jung-api-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-api/2.1/jung-api-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-api/2.1/jung-api-2.1-javadoc.jar) + * `jung-graph-impl`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-graph-impl/2.1/jung-graph-impl-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-graph-impl/2.1/jung-graph-impl-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-graph-impl/2.1/jung-graph-impl-2.1-javadoc.jar) + * `jung-algorithms`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-algorithms/2.1/jung-algorithms-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-algorithms/2.1/jung-algorithms-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-algorithms/2.1/jung-algorithms-2.1-javadoc.jar) + * `jung-io`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-io/2.1/jung-io-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-io/2.1/jung-io-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-io/2.1/jung-io-2.1-javadoc.jar) + * `jung-visualization`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-visualization/2.1/jung-visualization-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-visualization/2.1/jung-visualization-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-visualization/2.1/jung-visualization-2.1-javadoc.jar) + * `jung-samples`: [jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-samples/2.1/jung-samples-2.1.jar), [source jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-samples/2.1/jung-samples-2.1-sources.jar), [documentation jar](http://search.maven.org/remotecontent?filepath=net/sf/jung/jung-samples/2.1/jung-samples-2.1-javadoc.jar) + +To add a dependency on this release of JUNG using Maven, use the following for each JUNG subpackage that you need: + +```xml + + net.sf.jung + jung-[subpackage] + 2.1 + +``` + +### Snapshots + +Snapshots of JUNG built from the `master` branch are available through Maven using version `2.2-SNAPSHOT`. + +### Links + +* [GitHub project](https://github.com/jrtom/jung) +* [Issue tracker: report a defect or make a feature request](https://github.com/jrtom/jung/issues/new) +* [StackOverflow: Ask "how-to" and "why-didn't-it-work" questions](https://stackoverflow.com/questions/ask?tags=jung+java) + +### Contributions + +JUNG is currently administered primarily by @jrtom, one of the original co-creators of the JUNG project. + +Bug fixes (with tests) are appreciated and will generally be acted upon pretty quickly if the fix is a clear win. + +If you'd like to add a feature, or suggest a way that things could be done better, more cleanly, or more efficiently, we really appreciate it, we encourage you to [open an issue](https://github.com/jrtom/jung/issues/new), and you're welcome to make a pull request to show off a proof of concept. + +However, at the moment we're largely focused on some big architectural changes that are going to touch essentially everything in JUNG. Once those changes land, we'll have more time and energy available to consider other changes. diff -Nru libjung-free-java-2.0.1+dfsg/RELEASE.md libjung-free-java-2.1.1/RELEASE.md --- libjung-free-java-2.0.1+dfsg/RELEASE.md 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/RELEASE.md 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,229 @@ +# Releasing JUNG + +## Overview + +At a high level, the steps involved are as follows: + + * Preconditions + * Create a release branch + * Update versions + * Tag the release + * Build and deploy the release to sonatype + * Verify the release on sonatype + * Release the bits on oss.sonatype.org to the public repo + * Push the tag to github + + +Each step has some idiosyncracies, and follows below. + +> ***Note:*** *Any specific version numbers should be assumed to be examples and the real, +> current version numbers should be substituted.* + +## Detail + +### Preconditions + +> ***Note:*** *These preconditions include important minutiae of Maven +> deployments. Make sure you read the [OSSRH Guide] and the [Sonatype GPG +> blog post][GPG].* + +Releases involve releasing to Sonatype's managed repository which backs the +maven central repository. To push bits to sonatype requires: + + 1. an account on oss.sonatype.org + 2. permission for that account to push to your groupId + 3. a pgp certificate (via gnupg) with a published public key + 4. a [${HOME}/.m2/settings.xml][settings.xml] file containing the credentials + for the account created in step #1. **NOTE**: change the ID for the tag + in the example to `sonatype-nexus-staging`. + +The administrative steps above are all documented in Sonatype's +[OSSRH Guide]. The GPG instructions particular to this process can be found +in this [Sonatype GPG blog entry][GPG]. + +> ***Notes***: +> * *If you don't set up the `settings.xml` correctly on the machine you're using, +> you'll get an error that looks like this:* +> ```shell +> Failed to transfer file: https://oss.sonatype.org/service/local/staging/deploy/maven2/net/sf/jung/jung-parent/2.1/jung-parent-2.1.pom. +Return code is: 401, ReasonPhrase: Unauthorized. +> ``` +> * *As of this writing (March 2016) the default GPG installation on OS X will give you a +> binary called `gpg2` rather than `gpg`. This will cause the deploy script to fail. +> You should create a symbolic link called `gpg` (using `ln -s`) that points to `gpg2`.* + +### Create a release branch + +First check out the main project's master branch, and create a branch on which +to do the release work (to avoid clobbering anything on the master branch): + +```shell +git clone git@github.com:jrtom/jung.git jung_release +cd jung_release +git checkout -b release_2_1_branch +mvn verify +``` + +This generates a new branch, and does a full build to ensure that what is +currently at the tip of the branch is sound. + +### Update versions + +#### Increment SNAPSHOT dependency versions + +Do a quick check of the dependency versions to ensure that the project is +not relying on -SNAPSHOT dependencies. Since the project manages versions +in a `properties` section in the parent pom, the following is a useful tool: + +```shell +mvn -N versions:display-property-updates +``` + +Version properties will be generated and look like this: + +``` +... +[INFO] ------------------------------------------------------------------------ +[INFO] Building jung-parent 2.1-SNAPSHOT +[INFO] ------------------------------------------------------------------------ +[INFO] +[INFO] --- versions-maven-plugin:2.2:display-property-updates (default-cli) @ jung-parent --- +[INFO] artifact junit:junit: checking for updates from central +[INFO] artifact com.google.guava:guava: checking for updates from central +[INFO] +[INFO] The following version properties are referencing the newest available version: +[INFO] ${guava.version} ............................................... 19.0 +[INFO] The following version property updates are available: +[INFO] ${junit.version} ...................................... 3.8.1 -> 4.12 +... +``` + +For release, it's best to avoid updating older versions at the last minute, as +this requires more testing and investigation than one typically does at release. +But releases are gated on any -SNAPSHOT dependencies, so these should be +incremented. + +> ***Note:*** *If there is enough dependency lag, the release should be abandoned +> and dependencies should be incremented as a normal part of development.* + +#### Update the project's version. + +Update the versions of the project, like so (changing version numbers): + +```shell +mvn versions:set versions:commit -DnewVersion=2.1 +git commit -a +``` + +This will set all versions of projects connected in sections from +the parent pom - in short, all the parts of the project will be set to be (and +depend on) `2.1`. + +### Tag the release + +The release tags simply follow the format `jung-` so simply do this: + +```shell +git tag jung-2.1 +``` + +### Build and deploy the release to sonatype + +A convenience script exists to properly run a standard `mvn deploy` run +(which pushes built artifacts to the staging repository). It also activates +the release profile which ensures that the GnuPG plugin is run, signing the +binaries per Sonatype's requirements, adds in the generation of -javadoc and +-sources jars, etc. + +It's parameter is the label for your GnuPG key which can be seen by running +`gpg --list-keys` which supplies output similar to the following: + +``` +pub 2048D/E4382034 2014-12-16 +uid Some User (Maven Deployments) +``` + +> More detail about GPG and Sonatype repositories [in this blog post][GPG] + +Given the above example, you would then run: + +```shell +tools/mvn-deploy.sh E4382034 +``` + +... and the script will kick off the maven job, pausing when it first needs to +sign binaries to ask for your GnuPG certificate passphrase (if any). It then +pushes the binaries and signatures up to sonatype's staging repository. + +> ***Note:*** *Having out-of-date versions of Maven plugins can cause unexpected +> errors in the build/deploy process, including failure to find local binaries, +> and apparent compilation errors. In case of bizarre failures, update the +> plugins to the [latest versions](https://maven.apache.org/plugins/) and try again.* + +### Verify the release on sonatype + +Log in to `oss.sonatype.org` and select "Staging repositories". In the +main window, scroll to the botton where a staging repository named roughly +after the groupId will appear. + +> ***Note:*** *while this can be inspected, Sonatype performs several checks +> automatically when going through the release lifecycle, so generally it is +> not necessary to further inspect this staging repo.* + +Select the repository. You can check to ensure it is the correct repository by +descending the tree in the lower info window. If you are convinced it is the +correct one, click on the `close` button (in the upper menu bar) and optionally +enter a message (which will be included in any notifications people have set +up on that repository). Wait about 60 seconds or so and refresh. + +If successful, the `release` button will be visible. + +#### What if it goes wrong? + +If sonatype's analysis has rejected the release, you can check the information +in the lower info window to see what went wrong. Failed analyzes will show +in red, and the problem should be remedied and step #3 (Tag the release) should +be re-attempted with `tag -f jung-` once the fixes have been +committed. Then subsequent steps repeated. + +### Release the bits on oss.sonatype.org to the public repo + +Assuming sonatype's validation was successful, press the `release` button, +fill in the optional message, and the repository will be released and +automatically dropped once its contents have been copied out to the master +repository. + +At this point, the maven artifact(s) will be available for consumption by +maven builds within a few minutes (though it will not be present on + for about an hour). + +### Push the tag to github + +Since the release was committed to the maven repository, the exact project +state used to generate that should be marked. To push the above-mentioned +tag to github, just do the standard git command: + +```shell +git push --tags +``` + +This will create a new [release](https://github.com/jrtom/jung/releases) on GitHub. + +## Post-release + +Create a CL/commit that updates the versions from (for instance) +`2.1-SNAPSHOT` to the next development version (typically `2.2-SNAPSHOT`). +This commit should also contain any changes that were necessary to release +the project which need to be persisted (any upgraded dependencies, etc.) + +> ***Note:*** *Generally do not merge this directly into github as that will disrupt +> the standard MOE sync. It can either be created as a github pull-request and +> the `moe github_pull` command will turn it into a CL, or it can be created +> in a normal internal CL. The change can then by synced-out in the MOE run.* + +Once the release is done, and the tag is pushed, the branch can be safely +deleted. + +[GPG]: http://blog.sonatype.com/2010/01/how-to-generate-pgp-signatures-with-maven +[OSSRH Guide]: http://central.sonatype.org/pages/ossrh-guide.html +[settings.xml]: https://books.sonatype.com/nexus-book/reference/_adding_credentials_to_your_maven_settings.html diff -Nru libjung-free-java-2.0.1+dfsg/tools/deploy_snapshots.sh libjung-free-java-2.1.1/tools/deploy_snapshots.sh --- libjung-free-java-2.0.1+dfsg/tools/deploy_snapshots.sh 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/tools/deploy_snapshots.sh 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,13 @@ +# see https://coderwall.com/p/9b_lfq + +if [ "$TRAVIS_REPO_SLUG" == "jrtom/jung" ] && \ + [ "$TRAVIS_JDK_VERSION" == "oraclejdk7" ] && \ + [ "$TRAVIS_PULL_REQUEST" == "false" ] && \ + [ "$TRAVIS_BRANCH" == "master" ]; then + echo -e "Publishing maven snapshot...\n" + + mvn clean source:jar deploy --settings="tools/settings.xml" -DskipTests=true -Dmaven.javadoc.skip=true + + echo -e "Published maven snapshot" +fi + diff -Nru libjung-free-java-2.0.1+dfsg/tools/mvn-deploy.sh libjung-free-java-2.1.1/tools/mvn-deploy.sh --- libjung-free-java-2.0.1+dfsg/tools/mvn-deploy.sh 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/tools/mvn-deploy.sh 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,21 @@ +#!/bin/bash +if [ $# -lt 1 ]; then + echo "usage $0 [ ...]" + exit 1; +fi +key=$1 +shift + +#validate key +keystatus=$(gpg --list-keys | grep ${key} | awk '{print $1}') +if [ "${keystatus}" != "pub" ]; then + echo "Could not find public key with label ${key}" + echo -n "Available keys from: " + gpg --list-keys | grep --invert-match '^sub' + + exit 64 +fi + +mvn "$@" -P '!examples' -P sonatype-oss-release \ + -Dgpg.skip=false -Dgpg.keyname=${key} \ + clean site:jar deploy diff -Nru libjung-free-java-2.0.1+dfsg/tools/settings.xml libjung-free-java-2.1.1/tools/settings.xml --- libjung-free-java-2.0.1+dfsg/tools/settings.xml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/tools/settings.xml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,9 @@ + + + + sonatype-nexus-snapshots + ${env.CI_DEPLOY_USERNAME} + ${env.CI_DEPLOY_PASSWORD} + + + diff -Nru libjung-free-java-2.0.1+dfsg/.travis.yml libjung-free-java-2.1.1/.travis.yml --- libjung-free-java-2.0.1+dfsg/.travis.yml 1970-01-01 00:00:00.000000000 +0000 +++ libjung-free-java-2.1.1/.travis.yml 2016-09-07 14:41:04.000000000 +0000 @@ -0,0 +1,35 @@ +# Per https://docs.travis-ci.com/user/languages/java + +sudo: false + +language: java + +jdk: + - oraclejdk8 + - oraclejdk7 + - openjdk7 + +install: + - mvn -v + - mvn -B install -U -DskipTests=true + +script: + - mvn -B verify -U -Dmaven.javadoc.skip=true + +after_success: + - tools/deploy_snapshots.sh + +cache: + directories: + - ${HOME}/.m2 + +branches: + only: + - master + - /^release.*$/ + +env: + global: + - secure: "ZDWaFgXd/IyJUt4vs9pZnljLyhjbAzvTpkWMg+K0aaUhn+NV3cLHuKvghJXSXTF0/dbKRO4wVWat1xNZm6Ec1zWVeRmmJhoqjh65DozAslQdZAnbEGxEMdXPNqxFs0bEijEQ2GUbdh18tjqDonZn6gEXExr/OFiANJD9lkUWUZkX3TieXrMV8l4H5ywyokYzDO2iKRHKLZeci9oBWdmd6/ER9Luumn67wesZbGKZ9OSODtXGjqTdrh+WpvH9NmrqKCZLCFG1TLAD0cUkqKLba5aXTRD0WIRyX8iZwQzYF8v+j2812x3PHKKN85OGbBtVU+FrUqbvmYtTpGMjn4DKO1XMUvAXSXdpehY71Vw7eU5XXvm4OihOzDLW2hV//cE0yjuqjQDLC9jA2IACkTq7z8oQJ8JLzOxnWQAWJdS5893ZXOIBCn/yifVGIwDUA8lU2RiippCJkplpQoYMv//NN8t8Aazpz22yR38s5hBPGuz+70bTQ45O/uuhMa+81nOMzwbqq3Lu3aUNgqEzEHmEnX91XZLsKbPNL+i3TYf0mCF4EAXGdpV5pOXnjlCqO55SrxGojLKp/TcvMQT1KmD4nwvP5mL03UxqynDllLAz0AhLUZHdn5uCFTWIOto8mw27XJroSY99eiFhS5WqMuo7uxyJlHeqQTSFJx6ckGmBfSI=" + - secure: "lgiLAdXkJZzTwWmZoX5b+/ZZJUYvI1qB/tAlnZuCxiupxv3Lx9JcYH7eI5zKEjCc8ahwxF0A7ZAa+KPEeEQ9RlvrtSY1jBVHCZWIo1rvgg9Jeynhs9yYBXhcgxYl4jGlp7AZz7ZviHNLXtKbFlf/DJnCIruoIetW/Na0Y+k124OAOuHZrObOM5bhldVzYPMl8lZP171k67M3e9y5Lxv4o41DKOGNzBo3oGtfprW/cO3Nna6UfthbTuzrsqGXYPLU5PN3xhKyEgk8byC2hkzXZzje1IgKn6qLvkhKPNWmYRIf+DFO4f22bMLtzfXG2gfAb9RHMDl1TvemOBA/VIKhGAwnzhJqEkcVY482n39E9bq+/Wqhliwv+XVcBnh8oNMbr8OUEP9OO1ys4isNSMysaG3LPGdYt9d82CFpWDO1gFZ3qdxze/y7Fd/yC+mu62KFn6Jxg9w94kGIzWqrv9DUDgLMougCLgX+W+lhlLxgZ9ecwJPXXlKpoEPI+TSoEkurzcTlR1sRj1quAveaC8+FcxiQFV67XkCd7mQe2kUeNtb77kV1u6OpZL6MUZjV32FxZxxkZH3lAjOLt0hTyqGMpZXiVeJoUVXPOmX+7Em6O7Dd1j+q0lwt6n39YnWmTtLovJPVZDAZBgOvHPttSg5f854o6YYBBEZyrEiHE2zWgJo=" +