1 | /** \file |
2 | * \brief MLG is the main data structure for ModularMultilevelMixer |
3 | * |
4 | * \author Gereon Bartel |
5 | * |
6 | * \par License: |
7 | * This file is part of the Open Graph Drawing Framework (OGDF). |
8 | * |
9 | * \par |
10 | * Copyright (C)<br> |
11 | * See README.md in the OGDF root directory for details. |
12 | * |
13 | * \par |
14 | * This program is free software; you can redistribute it and/or |
15 | * modify it under the terms of the GNU General Public License |
16 | * Version 2 or 3 as published by the Free Software Foundation; |
17 | * see the file LICENSE.txt included in the packaging of this file |
18 | * for details. |
19 | * |
20 | * \par |
21 | * This program is distributed in the hope that it will be useful, |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
24 | * GNU General Public License for more details. |
25 | * |
26 | * \par |
27 | * You should have received a copy of the GNU General Public |
28 | * License along with this program; if not, see |
29 | * http://www.gnu.org/copyleft/gpl.html |
30 | */ |
31 | |
32 | #pragma once |
33 | |
34 | #include <ogdf/basic/Graph.h> |
35 | #include <ogdf/basic/GraphAttributes.h> |
36 | #include <vector> |
37 | #include <map> |
38 | |
39 | namespace ogdf { |
40 | |
41 | //Stores info on merging for a refinement level |
42 | struct NodeMerge |
43 | { |
44 | // Node/Edge IDs instead of pointers as the nodes themselves may be nonexistent. |
45 | std::vector<int> m_deletedEdges; |
46 | std::vector<int> m_changedEdges; |
47 | std::map<int, double> m_doubleWeight; // for changed and deleted edges |
48 | std::map<int, int> m_source; |
49 | std::map<int, int> m_target; |
50 | |
51 | int m_mergedNode; |
52 | std::vector< std::pair<int, double> > m_position; // optional information <target, distance>. mergedNode will be placed at average of relative distances to target. |
53 | |
54 | std::vector<int> m_changedNodes; // there may be placement strategies that use more than one reference-node. |
55 | std::map<int, double> m_radius; // for changed nodes and the merged node |
56 | |
57 | int m_level; |
58 | |
59 | |
60 | explicit NodeMerge(int level) : m_mergedNode(-1), m_level(level) { } |
61 | ~NodeMerge() { } |
62 | }; |
63 | |
64 | |
65 | class OGDF_EXPORT MultilevelGraph |
66 | { |
67 | private: |
68 | bool m_createdGraph; //used in destructor, TODO: check if it is needed |
69 | Graph * m_G; |
70 | GraphAttributes * m_GA; //<! Keeps layout info in replacement of information below (todo: remove them) |
71 | std::vector<NodeMerge *> m_changes; |
72 | NodeArray<double> m_radius; |
73 | double m_avgRadius; //stores average node radius for scaling and random layout purposes |
74 | |
75 | EdgeArray<double> m_weight; |
76 | |
77 | // Associations to index only as the node/edge may be nonexistent |
78 | NodeArray<int> m_nodeAssociations; |
79 | EdgeArray<int> m_edgeAssociations; |
80 | |
81 | std::vector<node> m_reverseNodeIndex; |
82 | std::vector<int> m_reverseNodeMergeWeight;//<! Keeps number of vertices represented by vertex with given index |
83 | std::vector<edge> m_reverseEdgeIndex; |
84 | |
85 | MultilevelGraph * removeOneCC(std::vector<node> &componentSubArray); |
86 | void copyFromGraph(const Graph &G, NodeArray<int> &nodeAssociations, EdgeArray<int> &edgeAssociations); |
87 | void prepareGraphAttributes(GraphAttributes &GA) const; |
88 | |
89 | void initReverseIndizes(); |
90 | void initInternal(); |
91 | |
92 | public: |
93 | ~MultilevelGraph(); |
94 | MultilevelGraph(); |
95 | explicit MultilevelGraph(Graph &G); |
96 | explicit MultilevelGraph(GraphAttributes &GA); |
97 | // if the Graph is available without const, no copy needs to be created. |
98 | MultilevelGraph(GraphAttributes &GA, Graph &G); |
99 | |
100 | // creates MultilevelGraph directly from GML file. |
101 | explicit MultilevelGraph(std::istream &is); |
102 | explicit MultilevelGraph(const char *filename); |
103 | |
104 | NodeArray<double> &getRArray() { return m_radius; } |
105 | EdgeArray<double> &getWArray() { return m_weight; } |
106 | |
107 | edge getEdge(unsigned int index); |
108 | node getNode(unsigned int index); |
109 | |
110 | double radius(node v) { return m_radius[v]; } |
111 | void radius(node v, double r) { m_radius[v] = r; } |
112 | double averageRadius() const { return m_avgRadius;} |
113 | |
114 | double x(node v) { return m_GA->x(v); } |
115 | double y(node v) { return m_GA->y(v); } |
116 | void x(node v, double x) { m_GA->x(v) = x;} |
117 | void y(node v, double y) { m_GA->y(v) = y;} |
118 | |
119 | void weight(edge e, double weight) { m_weight[e] = weight; } |
120 | double weight(edge e) { return m_weight[e]; } |
121 | |
122 | //returns the merge weight, i.e. the number of nodes represented by v on the current level |
123 | int mergeWeight(node v) {return m_reverseNodeMergeWeight[v->index()];} |
124 | |
125 | void moveToZero(); |
126 | |
127 | int getLevel(); |
128 | Graph & getGraph() { return *m_G; } |
129 | //! Returns attributes of current level graph as GraphAttributes |
130 | GraphAttributes & getGraphAttributes() const { return *m_GA; } |
131 | void exportAttributes(GraphAttributes &GA) const; |
132 | void exportAttributesSimple(GraphAttributes &GA) const; |
133 | void importAttributes(const GraphAttributes &GA); |
134 | void importAttributesSimple(const GraphAttributes &GA); |
135 | void reInsertGraph(MultilevelGraph &MLG); |
136 | void reInsertAll(std::vector<MultilevelGraph *> &components); |
137 | void copyNodeTo(node v, MultilevelGraph &MLG, std::map<node, node> &tempNodeAssociations, bool associate, int index = -1); |
138 | void copyEdgeTo(edge e, MultilevelGraph &MLG, std::map<node, node> &tempNodeAssociations, bool associate, int index = -1); |
139 | void writeGML(std::ostream &os); |
140 | void writeGML(const char *fileName); |
141 | |
142 | // the original graph will be cleared to save Memory |
143 | OGDF_DEPRECATED("Use ComponentSplitterLayout instead." ) |
144 | std::vector<MultilevelGraph *> splitIntoComponents(); |
145 | |
146 | bool postMerge(NodeMerge * NM, node merged); |
147 | //\a merged is the node now represented by \a theNode |
148 | bool changeNode(NodeMerge * NM, node theNode, double newRadius, node merged); |
149 | bool changeEdge(NodeMerge * NM, edge theEdge, double newWeight, node newSource, node newTarget); |
150 | bool deleteEdge(NodeMerge * NM, edge theEdge); |
151 | std::vector<edge> moveEdgesToParent(NodeMerge * NM, node theNode, node parent, bool deleteDoubleEndges, int adjustEdgeLengths); |
152 | NodeMerge * getLastMerge(); |
153 | node undoLastMerge(); |
154 | |
155 | void updateReverseIndizes(); |
156 | //sets the merge weights back to initial values |
157 | void updateMergeWeights(); |
158 | }; |
159 | |
160 | } |
161 | |