diff --git a/library/talipot-ogdf/CMakeLists.txt b/library/talipot-ogdf/CMakeLists.txt index 3a9042bc02..dbcf8d1acf 100644 --- a/library/talipot-ogdf/CMakeLists.txt +++ b/library/talipot-ogdf/CMakeLists.txt @@ -7,7 +7,8 @@ ENDIF(WIN32) DISABLE_COMPILER_WARNINGS() -SET(TalipotOGDF_SRCS src/TalipotToOGDF.cpp src/OGDFLayoutPluginBase.cpp) +SET(TalipotOGDF_SRCS src/TalipotToOGDF.cpp src/OGDFLayoutPluginBase.cpp + src/OGDFUtils.cpp) ADD_LIBRARY(${LibTalipotOGDFName} SHARED ${TalipotOGDF_SRCS}) @@ -21,7 +22,7 @@ INSTALL( ARCHIVE DESTINATION ${TalipotLibInstallDir}) INSTALL(FILES include/talipot/OGDFLayoutPluginBase.h - include/talipot/TalipotToOGDF.h + include/talipot/TalipotToOGDF.h include/talipot/OGDFUtils.h DESTINATION ${TalipotIncludeInstallDir}/talipot/) IF(TALIPOT_ACTIVATE_PYTHON_WHEEL_TARGET) diff --git a/library/talipot-ogdf/include/talipot/OGDFUtils.h b/library/talipot-ogdf/include/talipot/OGDFUtils.h new file mode 100644 index 0000000000..7929e4a694 --- /dev/null +++ b/library/talipot-ogdf/include/talipot/OGDFUtils.h @@ -0,0 +1,23 @@ +/** + * + * Copyright (C) 2023 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 TALIPOT_OGDF_UTILS_H +#define TALIPOT_OGDF_UTILS_H + +#include +#include + +TLP_OGDF_SCOPE tlp::Graph *convertOGDFGraphToTalipotGraph(ogdf::Graph &graph, + tlp::Graph *tlpGraph = nullptr); + +#endif // TALIPOT_OGDF_UTILS_H diff --git a/library/talipot-ogdf/src/OGDFUtils.cpp b/library/talipot-ogdf/src/OGDFUtils.cpp new file mode 100644 index 0000000000..5c7857f80a --- /dev/null +++ b/library/talipot-ogdf/src/OGDFUtils.cpp @@ -0,0 +1,38 @@ +/** + * + * Copyright (C) 2023 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 + +using namespace std; + +tlp::Graph *convertOGDFGraphToTalipotGraph(ogdf::Graph &graph, tlp::Graph *tlpGraph) { + if (!tlpGraph) { + tlpGraph = tlp::newGraph(); + } else { + tlpGraph->clear(); + } + + unordered_map nodesMap; + + for (ogdf::node n : graph.nodes) { + nodesMap[n] = tlpGraph->addNode(); + } + + for (ogdf::edge e : graph.edges) { + tlpGraph->addEdge(nodesMap[e->source()], nodesMap[e->target()]); + } + + return tlpGraph; +} diff --git a/plugins/import/CMakeLists.txt b/plugins/import/CMakeLists.txt index a72982d6b5..26e46ed00f 100644 --- a/plugins/import/CMakeLists.txt +++ b/plugins/import/CMakeLists.txt @@ -2,6 +2,7 @@ ADD_SUBDIRECTORY(SocialNetwork) ADD_SUBDIRECTORY(BibTeX) ADD_SUBDIRECTORY(Graphviz) ADD_SUBDIRECTORY(Git) +ADD_SUBDIRECTORY(OGDF) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${TalipotCoreBuildInclude} ${TalipotCoreInclude} ${TalipotGUIInclude}) diff --git a/plugins/import/OGDF/CMakeLists.txt b/plugins/import/OGDF/CMakeLists.txt new file mode 100644 index 0000000000..fc62e6e356 --- /dev/null +++ b/plugins/import/OGDF/CMakeLists.txt @@ -0,0 +1,25 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${TalipotCoreBuildInclude} + ${TalipotCoreInclude} ${OGDFInclude} ${TalipotOGDFInclude}) + +SET(PLUGINS_SRCS + OGDFPetersenGraph.cpp + OGDFRandomGeographicalGraph.cpp + OGDFRandomHierarchy.cpp + OGDFGlobeGraph.cpp + OGDFRegularLatticeGraph.cpp + OGDFRegularTree.cpp + OGDFCompleteKPartiteGraph.cpp) + +DISABLE_COMPILER_WARNINGS() + +TALIPOT_ADD_PLUGIN( + NAME + OGDFGraphGenerators + SRCS + ${PLUGINS_SRCS} + LINKS + ${LibTalipotCoreName} + ${LibTalipotOGDFName} + ${OGDF_LIBRARY} + INSTALL_DIR + ${TalipotPluginsInstallDir}) diff --git a/plugins/import/OGDF/OGDFCompleteKPartiteGraph.cpp b/plugins/import/OGDF/OGDFCompleteKPartiteGraph.cpp new file mode 100644 index 0000000000..0ed8eb1281 --- /dev/null +++ b/plugins/import/OGDF/OGDFCompleteKPartiteGraph.cpp @@ -0,0 +1,48 @@ +/** + * + * 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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // signature + "contains the positive values k1, k2, ..., kn.", +}; + +//================================================================================= + +class OGDFCompleteKPartiteGraph : public OGDFImportBase { +public: + PLUGININFORMATION("Complete K-partite Graph (OGDF)", "Antoine Lambert", "05/2024", + "Creates the complete k-partite graph K_{k1,k2,...,kn}.", "1.0", "OGDF") + + OGDFCompleteKPartiteGraph(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter>("signature", paramHelp[0].data(), "(10, 20, 30, 40)"); + } + + bool importOGDFGraph() override { + vector signature = {10, 20, 30, 40}; + if (dataSet != nullptr) { + dataSet->get("signature", signature); + } + auto signatureArray = ogdf::Array(signature.size()); + std::copy(signature.begin(), signature.end(), signatureArray.begin()); + ogdf::completeKPartiteGraph(G, signatureArray); + return true; + } +}; + +PLUGIN(OGDFCompleteKPartiteGraph) diff --git a/plugins/import/OGDF/OGDFGlobeGraph.cpp b/plugins/import/OGDF/OGDFGlobeGraph.cpp new file mode 100644 index 0000000000..211bc53c5b --- /dev/null +++ b/plugins/import/OGDF/OGDFGlobeGraph.cpp @@ -0,0 +1,55 @@ +/** + * + * 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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // meridians + "the number of meridians", + + // latitudes + "the number of latitudes", +}; + +//================================================================================= + +class OGDFGlobeGraph : public OGDFImportBase { +public: + PLUGININFORMATION("Globe Graph (OGDF)", "Antoine Lambert", "03/2024", + "Creates a globe graph with a given number of meridians and latitudes. " + "The graph will contain a node at each crossing of a meridian and a latitude, " + "and a node at each pole.", + "1.0", "OGDF") + + OGDFGlobeGraph(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("meridians", paramHelp[0].data(), "30"); + addInParameter("latitudes", paramHelp[1].data(), "30"); + } + + bool importOGDFGraph() override { + int meridians = 30; + int latitudes = 30; + if (dataSet != nullptr) { + dataSet->get("meridians", meridians); + dataSet->get("latitudes", latitudes); + } + ogdf::globeGraph(G, meridians, latitudes); + return true; + } +}; + +PLUGIN(OGDFGlobeGraph) diff --git a/plugins/import/OGDF/OGDFImportBase.h b/plugins/import/OGDF/OGDFImportBase.h new file mode 100644 index 0000000000..3daccc1962 --- /dev/null +++ b/plugins/import/OGDF/OGDFImportBase.h @@ -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 + +class OGDFImportBase : public tlp::ImportModule { + +public: + OGDFImportBase(tlp::PluginContext *context) : tlp::ImportModule(context) {} + virtual bool importOGDFGraph() = 0; + + bool importGraph() override { + if (importOGDFGraph()) { + convertOGDFGraphToTalipotGraph(G, graph); + return true; + } + return false; + } + +protected: + ogdf::Graph G; +}; \ No newline at end of file diff --git a/plugins/import/OGDF/OGDFPetersenGraph.cpp b/plugins/import/OGDF/OGDFPetersenGraph.cpp new file mode 100644 index 0000000000..e1cd40b082 --- /dev/null +++ b/plugins/import/OGDF/OGDFPetersenGraph.cpp @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2023-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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // n + "the number of nodes on the outer cycle", + + // m + "the length of jumps for the inner part", +}; + +//================================================================================= + +class OGDFPetersenGraph : public OGDFImportBase { +public: + PLUGININFORMATION( + "Petersen Graph (OGDF)", "Antoine Lambert", "11/2023", + "Creates an outer cycle of nodes 1, ..., n, each of which has a direct neighbor (a " + "corresponding inner node). For two outer nodes i, j, there is an edge between their " + "corresponding inner nodes if the absolute difference of i and j equals the jump length m.", + "1.0", "OGDF") + + OGDFPetersenGraph(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("n", paramHelp[0].data(), "5"); + addInParameter("m", paramHelp[1].data(), "2"); + } + + bool importOGDFGraph() override { + int n = 5; + int m = 2; + + if (dataSet != nullptr) { + dataSet->get("n", n); + dataSet->get("m", m); + } + + petersenGraph(G, n, m); + return true; + } +}; + +PLUGIN(OGDFPetersenGraph) diff --git a/plugins/import/OGDF/OGDFRandomGeographicalGraph.cpp b/plugins/import/OGDF/OGDFRandomGeographicalGraph.cpp new file mode 100644 index 0000000000..4e28dc6539 --- /dev/null +++ b/plugins/import/OGDF/OGDFRandomGeographicalGraph.cpp @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2023-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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // n + "the number of nodes in the graph", + + // threshold + "threshold for edge insertion", +}; + +//================================================================================= + +class OGDFRandomGeographicalGraph : public OGDFImportBase { +public: + PLUGININFORMATION("Random Geographical Graph (OGDF)", "Antoine Lambert", "11/2023", + "Creates a random geometric graph where edges are created based on " + "their distance and the weight of nodes", + "1.0", "OGDF") + + OGDFRandomGeographicalGraph(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("n", paramHelp[0].data(), "100"); + addInParameter("threshold", paramHelp[1].data(), "0.7"); + } + + bool importOGDFGraph() override { + int n = 100; + double threshold = 0.7; + + if (dataSet != nullptr) { + dataSet->get("n", n); + dataSet->get("threshold", threshold); + } + + ogdf::Array weights = ogdf::Array(n); + for (int &w : weights) { + w = tlp::randomNumber(n); + } + uniform_int_distribution dist(0, n); + ogdf::randomGeographicalThresholdGraph(G, weights, dist, 0.7); + return true; + } +}; + +PLUGIN(OGDFRandomGeographicalGraph) diff --git a/plugins/import/OGDF/OGDFRandomHierarchy.cpp b/plugins/import/OGDF/OGDFRandomHierarchy.cpp new file mode 100644 index 0000000000..243193e4cc --- /dev/null +++ b/plugins/import/OGDF/OGDFRandomHierarchy.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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // n + "the number of nodes", + // m + "the number of edges", + // planar + "determines if the resulting graph is (level-)planar", + // singleSource + "determines if the graph is a single-source graph", + // longEdges + "determines if the graph has long edges (spanning 2 layers or more); " + "otherwise the graph is proper"}; + +//================================================================================= + +class OGDFRandomHierarchy : public OGDFImportBase { +public: + PLUGININFORMATION("Random Hierarchy (OGDF)", "Antoine Lambert", "02/2024", + "Creates a random hierarchical graph", "1.0", "OGDF") + + OGDFRandomHierarchy(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("n", paramHelp[0].data(), "1000"); + addInParameter("m", paramHelp[1].data(), "2000"); + addInParameter("planar", paramHelp[2].data(), "true"); + addInParameter("singleSource", paramHelp[3].data(), "true"); + addInParameter("longEdges", paramHelp[4].data(), "false"); + } + + bool importOGDFGraph() override { + int n = 100; + int m = 100; + bool planar = false; + bool singleSource = false; + bool longEdges = true; + + if (dataSet != nullptr) { + dataSet->get("n", n); + dataSet->get("m", m); + dataSet->get("planar", planar); + dataSet->get("singleSource", singleSource); + dataSet->get("longEdges", longEdges); + } + + ogdf::randomHierarchy(G, n, m, planar, singleSource, longEdges); + return true; + } +}; + +PLUGIN(OGDFRandomHierarchy) diff --git a/plugins/import/OGDF/OGDFRegularLatticeGraph.cpp b/plugins/import/OGDF/OGDFRegularLatticeGraph.cpp new file mode 100644 index 0000000000..9adde4cb11 --- /dev/null +++ b/plugins/import/OGDF/OGDFRegularLatticeGraph.cpp @@ -0,0 +1,69 @@ +/** + * + * 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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // n + "the number of nodes in the graph, must be at least 4", + + // k + "the degree of each node, must be an even number between 0 and n-2", +}; + +//================================================================================= + +class OGDFRegularLatticeGraph : public OGDFImportBase { +public: + PLUGININFORMATION("Regular Lattice Graph (OGDF)", "Antoine Lambert", "03/2024", + "Generates a cycle on n sequential nodes, where any two nodes whose" + " distance is at most k / 2 are connected by an additional edge.", + "1.0", "OGDF") + + OGDFRegularLatticeGraph(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("n", paramHelp[0].data(), "50"); + addInParameter("k", paramHelp[1].data(), "6"); + } + + bool importOGDFGraph() override { + int n = 50; + int k = 6; + if (dataSet != nullptr) { + dataSet->get("n", n); + dataSet->get("k", k); + } + + if (n < 4) { + if (pluginProgress) { + pluginProgress->setError("n must be at least 4"); + } + return false; + } + if (k < 0 || k > n - 2 || k % 2 == 1) { + if (pluginProgress) { + pluginProgress->setError("k must be an even number between 0 and " + to_string(k)); + } + return false; + } + ogdf::regularLatticeGraph(G, n, k); + return true; + } + +private: +}; + +PLUGIN(OGDFRegularLatticeGraph) diff --git a/plugins/import/OGDF/OGDFRegularTree.cpp b/plugins/import/OGDF/OGDFRegularTree.cpp new file mode 100644 index 0000000000..677ddf417d --- /dev/null +++ b/plugins/import/OGDF/OGDFRegularTree.cpp @@ -0,0 +1,56 @@ +/** + * + * 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 "OGDFImportBase.h" + +using namespace std; + +static constexpr string_view paramHelp[] = { + // n + "the number of nodes of the tree", + + // children + "the number of children per node, if number of nodes does not allow a regular node, the last " + "node will have fewer children", +}; + +//================================================================================= + +class OGDFRegularTree : public OGDFImportBase { +public: + PLUGININFORMATION("Regular Tree (OGDF)", "Antoine Lambert", "03/2024", + "Generates a regular tree where each node has the same number of children.", + "1.0", "OGDF") + + OGDFRegularTree(tlp::PluginContext *context) : OGDFImportBase(context) { + addInParameter("n", paramHelp[0].data(), "106"); + addInParameter("children", paramHelp[1].data(), "5"); + } + + bool importOGDFGraph() override { + int n = 106; + int children = 5; + if (dataSet != nullptr) { + dataSet->get("n", n); + dataSet->get("children", children); + } + ogdf::regularTree(G, n, children); + return true; + } + +private: +}; + +PLUGIN(OGDFRegularTree)