сравнение фреймворков для рисования графов Java с открытым исходным кодом (JUNG и Prefuse) для рисования топологии сети

какую из фреймворков для рисования графов Java с открытым исходным кодом использовать для сетевой диаграммы со следующими требованиями? В графе будет менее 1000 узлов.

1) имеет параллельные ребра
2) направленные и неориентированные ребра в пределах одного графа
3) узлы представлены изображениями
4) взаимодействие пользователя с узлами и ребрами
5) динамическое добавление / удаление узлов и ребер
6) множественная маркировка на узлах и ребрах, разные уровни маркировки могут быть включены / выключены пользователями. (например, рисование в слоях и включение / выключение слоя)
7) различные алгоритмы компоновки для отображения топологий звезды, кольца, сетки

Я оценил JUNG и Prefuse. Это то, что я нашел для каждого из своих требований.

1) Prefuse не может отображать параллельные края, пока JUNG поддерживает его. Можно ли изменить код предварительного предохранителя для отображения параллельных краев? Поскольку это включает в себя базовые изменения уровня данных, я считаю, что это будет сложнее, чем изменение обычного настраиваемого рендеринга.

2) Я не нашел никаких ссылок на комбинированный граф (как направленные, так и неориентированные ребра) как в prefuse, так и в JUNG. Кто-нибудь знает иначе?

3) Это кажется простым как с Prefuse, так и с JUNG.

4) И снова prefuse и JUNG обеспечивают поддержку взаимодействия с пользователем.

5) И предварительный предохранитель, и JUNG поддерживают его. Как работает каждый фреймворк при перерисовке графика? В другом посте я видел, что prefuse плохо работает для динамических обновлений (Prefuse Toolkit: динамическое добавление узлов и ребер)

6) Это сводится к модификации графика и его перерисовке. Таким образом, вопрос становится таким же, как 5)

7) И JUNG, и prefuse имеют несколько алгоритмов компоновки. Но когда я попытался отобразить один и тот же набор данных с помощью FruchtermanReingoldLayout как в JUNG, так и в Prefuse, я получил разные изображения. Есть идеи, почему? Каким-то образом кажется, что алгоритмы компоновки в Prefuse лучше отображают компоновку, чем в JUNG (я думаю, рендеринг тоже лучше), хотя большинство алгоритмов компоновки в Prefuse основаны на реализации JUNG. Предварительные макеты, такие как ForceDirectedLayout / FruchtermanReingoldLayout и CircleLayout, напрямую сопоставляются с топологиями звезды, круга и сетки.

Вне этих требований prefuse имеет хорошую поддержку выражений и языка запросов, но похоже, что он не развивается активно, в отличие от JUNG. у кого лучше визуализация? Есть предложения, какой из них подойдет и как преодолеть недостатки?

Любые другие фреймворки, которые я могу использовать?


person user572964    schedule 12.01.2011    source источник
comment
+1 за это. Мне нравится, что вы проделали большую предварительную работу по оценке двух возможностей и представили свои выводы. Помимо вашего вопроса, здесь есть большая ценность для других. Это может быть лучший первый вопрос для нового пользователя, которого я видел здесь за два года. Я бы отдал больше, если бы мог.   -  person duffymo    schedule 12.01.2011


Ответы (5)


Несколько лет назад (2007?) Я использую prefuse для визуализации записей данных о звонках. Я рассмотрел prefuse, jung, jgraph и некоторые другие и выбрал prefuse. Поначалу сложно представить себе предварительный предохранитель, но как только я познакомился с ним, его действительно легко (расширить) и весело использовать. Думаю, то же самое можно сказать и о JUNG, но я никогда не пробовал.

1) В prefuse очень легко добавить свой собственный рендерер для рисования параллельных краев - вы можете создать подкласс EdgeRenderer по умолчанию и переопределить метод render (). Нет необходимости в «основных изменениях уровня данных». Все это находится в части просмотра, если вы хотите думать об этом как о материале MVC.

2) Это вообще не проблема. Есть несколько способов сделать это: 1) У вас может быть два средства визуализации - один для рисования направленных краев и один для рисования неориентированных краев, и они будут работать нормально и соответствующим образом сгруппировать края. 2) Поместите флаг (добавьте логический столбец в кортеж вспомогательной таблицы в предварительном соединении), чтобы указать, направлен ли край, и пропустите часть рисования стрелки в EdgeRender в соответствии с этим флагом.

3) Это очень просто

4) ditto (то же самое)

5) Последний выпуск предварительных предохранителей - это «бета-версия предварительного предохранителя 2007.10.21». Я использовал тот, который был до этого, у которого есть возможное состояние гонки при динамическом добавлении или удалении узлов - я думаю, ему не хватало нескольких синхронизированных ключевых слов. Я решил это, остановив всю анимацию и действия (цвет, размер, макет) при добавлении или удалении узлов - также не забудьте обновить свои индексы lucene (если вы используете его встроенную поисковую систему lucene ). Предполагается, что последняя версия решит эту проблему с гонкой, но у меня никогда не было возможности попробовать ее.

6) Поскольку вы упомянули «множественные метки», я думаю, что дело не в «изменении графика и его перерисовке» - это просто вопрос настройки ваших модулей рендеринга меток / краев, чтобы они отображали только соответствующие метки, так что это не большая проблема. . Также я не думаю, что это вообще связано с 5.

7) Я не удивлен, что prefuse и JUNG-рендеринг FruchtermanReingoldLayout отличаются - есть несколько факторов, которые могут повлиять на этот один из них - начальный узел, на котором каждая реализация запускает вычисление, поэтому я бы не стал сильно беспокоиться об этой проблеме. Довольно легко опробовать различные встроенные алгоритмы компоновки графов в prefuse, так что вы можете пойти дальше и проверить, какой из них ближе всего к тому, что вы хотели бы иметь. Взгляните на RadialLayout и BalloonTreeLayout для звездообразного макета. ForceDirectedLayout требует довольно много итераций, чтобы размещение узлов было «стабильным». Обратите внимание, что эти итерации не обязательно показывать, поэтому вы можете запустить их в фоновом режиме и визуализировать окончательный результат.

Я не использую JUNG, поэтому особо не могу его комментировать.

Основываясь на моем опыте работы с предохранителями, я настоятельно рекомендую их из-за очень хорошо (IMHO) продуманной конструкции и разделения ответственности между компонентами. Джеффри Хир (автор prefuse) действительно хорошо поработал.

На что следует обратить внимание, если вы используете предварительный предохранитель (это две "больные пальцы", которые я отчетливо помню при работе с предварительным предохранителем):

1) Есть ошибка, из-за которой при уменьшении масштаба метки узла не масштабируются должным образом, так что он выходит за пределы ограничивающей рамки узла, что оставляет артефакты рисования шрифта при перемещении узла, потому что средство визуализации только очищает и перерисовывает материал в пределах границы узла. коробка. IIRC. Это вызвано ошибкой в ​​самой метрике шрифта AWT. Обходной путь - оставить достаточно места между меткой и ограничивающей рамкой узла.

2) При расширении встроенных макетов вы можете столкнуться с одной или двумя «проблемами области видимости», когда член суперкласса, к которому вы хотели бы иметь доступ, получает частный атрибут вместо защищенного, поэтому решение состоит в том, чтобы либо изменить саму библиотеку или создайте новый класс без наследования (это может быть немного болезненно!). Думаю, то же самое можно сказать и о некоторых других java-библиотеках. Не у всех есть преимущество ретроспективного взгляда нет? :)

Поскольку вы задали этот вопрос около месяца назад (на момент написания этой статьи), я хотел бы знать, каким было ваше решение и как оно обернулось для вас, если вы продолжили реализацию.

person holygeek    schedule 10.02.2011

Я один из создателей и сопровождающих JUNG, так что имейте это в виду при ответах ниже.

Однако сначала я должен сказать, что автор Prefuse - друг друга (и да, мы встречались), и он проделал большую работу. У меня нет опыта работы с Prefuse, но я видел несколько красивых визуализаций, созданных с его помощью.

Вот ответы на эти вопросы для JUNG. Некоторые из них ((1), (2), (4) продемонстрированы в PluggableRendererDemo:

  1. Поддерживается (вам понадобится правильная модель данных, не все поддерживают параллельные ребра по соображениям производительности)
  2. Поддерживается (опять же, вам нужна правильная модель данных)
  3. Поддерживается (см. ImageShaperDemo)
  4. Поддерживается (большинство демонстраций)
  5. Поддерживается (см. GraphEditorDemo)
  6. Непосредственно не поддерживается, хотя вы, безусловно, можете динамически изменять метки и использовать HTML для визуализации сложных меток.
  7. Алгоритмы компоновки JUNG больше подходят для общих сетей (за некоторыми исключениями для деревьев и т. Д.). Однако вы, безусловно, можете создать свои собственные алгоритмы компоновки, и многие так и поступили.

Надеюсь это поможет.

person Joshua O'Madadhain    schedule 18.03.2011

Я знаю, что вы указали jung и prefuse, но ... У меня был хороший опыт работы с TomSawyer и yFiles. Список требований, который вы предложили, очень прост для этих двух - и они поддерживают гораздо больше.

Ран.

person Ran Biron    schedule 12.01.2011

Я бы посоветовал также оценить JGraph.

person Thomas the Tank Engine    schedule 13.01.2011

Мне нравится ответ @hollygeek. Вот моя реализация решения для 2 (как направленных, так и неориентированных ребер) для Prefuse:

public class MyRenderFactory implements RendererFactory
{
    private NodeRenderer nodeRenderer = new NodeRenderer();
    private EdgeRenderer defaultEdgeRenderer = new EdgeRenderer();
    private EdgeRenderer undirectedEdgeRenderer = new EdgeRenderer(EdgeRenderer.EdgeType.LINE, EdgeRenderer.EdgeArrowType.NONE);

    public static String directedness = "myEdgeDirectedness";

    public enum EdgeDirected
    {
        directed, undirected;

        public static EdgeDirected fromIsDirected(boolean isDirected)
        {
            if (isDirected)
            {
                return directed;
            }
            return undirected;
        }
    }

    @Override
    public Renderer getRenderer(VisualItem<?> visualItem)
    {
        if (visualItem instanceof EdgeItem)
        {
            if (visualItem.get(directedness).equals(PrefuseGraphConverter.EdgeDirected.undirected))
            {
                return undirectedEdgeRenderer;
            }
            return defaultEdgeRenderer;
        }
        return nodeRenderer;
    }
}

... в другом месте, где создается график ...

MyRenderFactory.EdgeDirected directedness =
        MyRenderFactory.EdgeDirected.fromIsDirected(myEdge.isDirected());
prefuseEdge.set(MyRenderFactory.directedness, directedness);
person Gladclef    schedule 22.03.2017