From 8de8ebd0dc0a4d749eafc1d275ba5b98a9c307c9 Mon Sep 17 00:00:00 2001 From: Antoine Lambert Date: Fri, 14 Jun 2024 01:17:29 +0200 Subject: [PATCH] plugins/layout/OGDF: Wrap new planar layout algorithms --- plugins/layout/OGDF/CMakeLists.txt | 7 +- plugins/layout/OGDF/OGDFFPPLayout.cpp | 34 +++++++++ plugins/layout/OGDF/OGDFMixedModel.cpp | 68 ++++++++++++++++++ plugins/layout/OGDF/OGDFPlanarDrawLayout.cpp | 34 +++++++++ plugins/layout/OGDF/OGDFPlanarLayoutBase.h | 43 +++++++++++ .../layout/OGDF/OGDFPlanarStraightLayout.cpp | 35 +++++++++ plugins/layout/OGDF/OGDFSchnyderLayout.cpp | 71 +++++++++++++++++++ 7 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 plugins/layout/OGDF/OGDFFPPLayout.cpp create mode 100644 plugins/layout/OGDF/OGDFMixedModel.cpp create mode 100644 plugins/layout/OGDF/OGDFPlanarDrawLayout.cpp create mode 100644 plugins/layout/OGDF/OGDFPlanarLayoutBase.h create mode 100644 plugins/layout/OGDF/OGDFPlanarStraightLayout.cpp create mode 100644 plugins/layout/OGDF/OGDFSchnyderLayout.cpp diff --git a/plugins/layout/OGDF/CMakeLists.txt b/plugins/layout/OGDF/CMakeLists.txt index 713d4a88b9..20b066d993 100644 --- a/plugins/layout/OGDF/CMakeLists.txt +++ b/plugins/layout/OGDF/CMakeLists.txt @@ -22,7 +22,12 @@ SET(PLUGINS_SRCS OGDFTileToRowsPacking.cpp OGDFPlanarizationLayout.cpp OGDFDTreeMultilevelEmbedder.cpp - OGDFRadialTreeLayout.cpp) + OGDFRadialTreeLayout.cpp + OGDFMixedModel.cpp + OGDFSchnyderLayout.cpp + OGDFFPPLayout.cpp + OGDFPlanarDrawLayout.cpp + OGDFPlanarStraightLayout.cpp) DISABLE_COMPILER_WARNINGS() diff --git a/plugins/layout/OGDF/OGDFFPPLayout.cpp b/plugins/layout/OGDF/OGDFFPPLayout.cpp new file mode 100644 index 0000000000..531af1d9ae --- /dev/null +++ b/plugins/layout/OGDF/OGDFFPPLayout.cpp @@ -0,0 +1,34 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#include + +#include "OGDFPlanarLayoutBase.h" + +// static constexpr std::string_view paramHelp[] = {}; + +class OGDFFPPLayout : public OGDFPlanarLayoutBase { + +public: + PLUGININFORMATION("FPP (OGDF)", "", "", "", "1.0", "Planar") + OGDFFPPLayout(const tlp::PluginContext *context) + : OGDFPlanarLayoutBase(context, tlp::getOGDFLayoutModule(context)), + fppLayout(static_cast(ogdfLayoutAlgo)) {} + + void beforeCall() override {} + +private: + ogdf::FPPLayout *fppLayout; +}; + +PLUGIN(OGDFFPPLayout) diff --git a/plugins/layout/OGDF/OGDFMixedModel.cpp b/plugins/layout/OGDF/OGDFMixedModel.cpp new file mode 100644 index 0000000000..c0b7594c37 --- /dev/null +++ b/plugins/layout/OGDF/OGDFMixedModel.cpp @@ -0,0 +1,68 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#include +#include +#include + +#include + +#include "OGDFPlanarLayoutBase.h" + +#define ELT_CROSSINGS_BEAUTIFIER "crossings beautifier" +#define ELT_CROSSINGS_BEAUTIFIER_LIST "MMDummyCrossingsBeautifier;MMCBDoubleGrid;MMCBLocalStretch" +static const std::vector> + crossingsBeautifier = { + []() { return new ogdf::MMDummyCrossingsBeautifier; }, + []() { return new ogdf::MMCBDoubleGrid; }, + []() { return new ogdf::MMCBLocalStretch; }, +}; +static const char *crossingsBeautifierValuesDescription = + "MMDummyCrossingsBeautifier (does no beautification at " + "all)
MMCBDoubleGrid (crossings beautifier using grid " + "doubling)
MMCBLocalStretch (crossings beautifier using a local stretch " + "strategy)"; + +static constexpr std::string_view paramHelp[] = { + // crossings beautifiers + "The crossings beautifier is applied as preprocessing to dummy nodes in the graph that " + "actually represent crossings. By default, crossings might look weird, since they are not " + "drawn as two crossing horizontal and vertical lines; the other available crossings beautifier " + "correct this.", +}; + +class OGDFMixedModelLayout : public OGDFPlanarLayoutBase { + +public: + PLUGININFORMATION("Mixed Model (OGDF)", "", "", "", "1.0", "Planar") + OGDFMixedModelLayout(const tlp::PluginContext *context) + : OGDFPlanarLayoutBase(context, tlp::getOGDFLayoutModule(context)), + mixedModel(static_cast(ogdfLayoutAlgo)) { + addInParameter(ELT_CROSSINGS_BEAUTIFIER, paramHelp[0].data(), + ELT_CROSSINGS_BEAUTIFIER_LIST, true, + crossingsBeautifierValuesDescription); + } + + void beforeCall() override { + tlp::StringCollection sc; + if (dataSet && dataSet->get(ELT_CROSSINGS_BEAUTIFIER, sc)) { + mixedModel->setCrossingsBeautifier(crossingsBeautifier[sc.getCurrent()]()); + } + tlpToOGDF->makeOGDFGraphSimple(); + } + +private: + ogdf::MixedModelLayout *mixedModel; +}; + +PLUGIN(OGDFMixedModelLayout) diff --git a/plugins/layout/OGDF/OGDFPlanarDrawLayout.cpp b/plugins/layout/OGDF/OGDFPlanarDrawLayout.cpp new file mode 100644 index 0000000000..0aca890cd9 --- /dev/null +++ b/plugins/layout/OGDF/OGDFPlanarDrawLayout.cpp @@ -0,0 +1,34 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#include + +#include "OGDFPlanarLayoutBase.h" + +// static constexpr std::string_view paramHelp[] = {}; + +class OGDFPlanarDrawLayout : public OGDFPlanarLayoutBase { + +public: + PLUGININFORMATION("Planar Draw (OGDF)", "", "", "", "1.0", "Planar") + OGDFPlanarDrawLayout(const tlp::PluginContext *context) + : OGDFPlanarLayoutBase(context, tlp::getOGDFLayoutModule(context)), + planarDrawLayout(static_cast(ogdfLayoutAlgo)) {} + + void beforeCall() override {} + +private: + ogdf::PlanarDrawLayout *planarDrawLayout; +}; + +PLUGIN(OGDFPlanarDrawLayout) diff --git a/plugins/layout/OGDF/OGDFPlanarLayoutBase.h b/plugins/layout/OGDF/OGDFPlanarLayoutBase.h new file mode 100644 index 0000000000..316e2a1568 --- /dev/null +++ b/plugins/layout/OGDF/OGDFPlanarLayoutBase.h @@ -0,0 +1,43 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#ifndef OGDF_PLANAR_LAYOUT_BASE_H +#define OGDF_PLANAR_LAYOUT_BASE_H + +#include + +#include +#include + +class OGDFPlanarLayoutBase : public tlp::OGDFLayoutPluginBase { + +public: + OGDFPlanarLayoutBase(const tlp::PluginContext *context, ogdf::LayoutModule *ogdfLayoutAlgo) + : OGDFLayoutPluginBase(context, ogdfLayoutAlgo) {} + + bool check(std::string &errorMsg) override { + auto connectedComponents = tlp::ConnectedTest::computeConnectedComponents(graph); + for (const auto &connectedComponent : connectedComponents) { + auto *sg = graph->inducedSubGraph(connectedComponent); + if (!tlp::PlanarityTest::isPlanar(sg)) { + graph->delSubGraph(sg); + errorMsg = "Each connected component must be planar."; + return false; + } + graph->delSubGraph(sg); + } + return true; + } +}; + +#endif // OGDF_PLANAR_LAYOUT_BASE_H \ No newline at end of file diff --git a/plugins/layout/OGDF/OGDFPlanarStraightLayout.cpp b/plugins/layout/OGDF/OGDFPlanarStraightLayout.cpp new file mode 100644 index 0000000000..60ecd9293d --- /dev/null +++ b/plugins/layout/OGDF/OGDFPlanarStraightLayout.cpp @@ -0,0 +1,35 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#include + +#include "OGDFPlanarLayoutBase.h" + +// static constexpr std::string_view paramHelp[] = {}; + +class OGDFPlanarStraightLayout : public OGDFPlanarLayoutBase { + +public: + PLUGININFORMATION("Planar Straight (OGDF)", "", "", "", "1.0", "Planar") + OGDFPlanarStraightLayout(const tlp::PluginContext *context) + : OGDFPlanarLayoutBase(context, + tlp::getOGDFLayoutModule(context)), + planarStraightLayout(static_cast(ogdfLayoutAlgo)) {} + + void beforeCall() override {} + +private: + ogdf::PlanarStraightLayout *planarStraightLayout; +}; + +PLUGIN(OGDFPlanarStraightLayout) diff --git a/plugins/layout/OGDF/OGDFSchnyderLayout.cpp b/plugins/layout/OGDF/OGDFSchnyderLayout.cpp new file mode 100644 index 0000000000..f849a01807 --- /dev/null +++ b/plugins/layout/OGDF/OGDFSchnyderLayout.cpp @@ -0,0 +1,71 @@ +/** + * + * Copyright (C) 2024 The Talipot developers + * + * Talipot is a fork of Tulip, created by David Auber + * and the Tulip development Team from LaBRI, University of Bordeaux + * + * See the AUTHORS file at the top-level directory of this distribution + * License: GNU General Public License version 3, or any later version + * See top-level LICENSE file for more information + * + */ + +#include + +#include + +#include "OGDFPlanarLayoutBase.h" + +#define ELT_COMBINATORIAL_OBJECTS "combinatorial objects" +#define ELT_COMBINATORIAL_OBJECTS_LIST "VerticesMinusDepth;Faces" +static const std::vector combinatorialObjects = { + ogdf::SchnyderLayout::CombinatorialObjects::VerticesMinusDepth, + ogdf::SchnyderLayout::CombinatorialObjects::Faces}; + +static constexpr std::string_view paramHelp[] = { + // combinatorial objects + "Each node in a Schnyder wood splits the graph into three regions. The barycentric coordinates " + "of the nodes are given by the count of combinatorial objects in these regions.", +}; + +static const char *combinatorialObjectsValuesDescription = + "VerticesMinusDepth (Count the number of vertices in each region i and subtract " + "the depth of the (i-1)-path of the node. The grid layout size is (n - 2) × (n - " + "2).)
" + "Faces (Count the number of faces in each region i. The grid layout size is (2n - 5) " + "× (2n - 5).)
"; + +class OGDFSchnyderLayout : public OGDFPlanarLayoutBase { + +public: + PLUGININFORMATION( + "Schnyder (OGDF)", "Antoine Lambert", "O6/2024", + "This algorithm draws a planar graph G straight-line without crossings. G (with |V| ≥ 3) " + "must not contain self-loops or multiple edges. The algorithm runs in three phases. In the " + "first phase, the graph is augmented by adding new artificial edges to get a triangulated " + "plane graph. Then, a partition of the set of interior edges in three trees (also called " + "Schnyder trees) with special orientation properties is derived. In the third step, the " + "actual coordinates are computed.", + "1.0", "Planar") + OGDFSchnyderLayout(const tlp::PluginContext *context) + : OGDFPlanarLayoutBase(context, tlp::getOGDFLayoutModule(context)), + schnyderLayout(static_cast(ogdfLayoutAlgo)) { + addInParameter(ELT_COMBINATORIAL_OBJECTS, paramHelp[0].data(), + ELT_COMBINATORIAL_OBJECTS_LIST, true, + combinatorialObjectsValuesDescription); + } + + void beforeCall() override { + tlp::StringCollection sc; + if (dataSet->get(ELT_COMBINATORIAL_OBJECTS, sc)) { + schnyderLayout->setCombinatorialObjects(combinatorialObjects[sc.getCurrent()]); + } + tlpToOGDF->makeOGDFGraphSimple(); + } + +private: + ogdf::SchnyderLayout *schnyderLayout; +}; + +PLUGIN(OGDFSchnyderLayout)