PeriDyno 1.0.0
Loading...
Searching...
No Matches
AutoLayoutDAG.cpp
Go to the documentation of this file.
1#include "AutoLayoutDAG.h"
2#include <cmath>
3#include <algorithm>
4namespace dyno
5{
7 {
8 pDAG = dag;
9
10 auto& vertices = pDAG->vertices();
11 auto& edges = pDAG->edges();
12 auto& OtherVerticesDirect = pDAG->getOtherVertices();
13
14 for (auto v : vertices)
15 {
16 mVertices.insert(v);
17 }
18
19 for (auto s : OtherVerticesDirect)
20 {
21 OtherVertices.insert(s);
22
23 }
24
25 for (auto it : edges)
26 {
27 ObjectId v = it.first;
28 for (auto w : it.second)
29 {
30 // Add an edge (v, w).
31 mEdges[v].insert(w);
32
33 //Add a reverse edge (w, v)
34 mReverseEdges[w].insert(v);
35 }
36 }
37 }
38
40 {
41 for (auto it : mEdges)
42 {
43 it.second.clear();
44 }
45 mEdges.clear();
46
47 for (auto it : mReverseEdges)
48 {
49 it.second.clear();
50 }
51 mReverseEdges.clear();
52
53 mLayers.clear();
54 mXCoordinate.clear();
55
56 for (size_t i = 0; i < mNodeLayers.size(); i++)
57 {
58 mNodeLayers[i].clear();
59 }
60 mNodeLayers.clear();
61 }
62
71
73 {
74 int maxLayer = mVertices.size();
75 std::map<ObjectId, bool> visited;
76 std::map<ObjectId, bool> isActive;
77
78 std::queue<ObjectId> activeId;
79
80 //Push vertices that have not outgoing edges into a queue
81 for (auto v : mVertices)
82 {
83 if (mEdges[v].size() == 0) {
84 mLayers[v] = maxLayer;
85
86 activeId.push(v);
87 isActive[v] = true;
88 }
89 else {
90 mLayers[v] = 0;
91
92 isActive[v] = false;
93 }
94
95 visited[v] = false;
96 }
97
98 auto BFS = [&](ObjectId v)
99 {
100 // Mark the current node as visited.
101 visited[v] = true;
102
103 for (auto vid : mReverseEdges[v])
104 {
105 if (!visited[vid] && !isActive[vid]) {
106 activeId.push(vid);
107 isActive[vid] = true;
108 }
109 }
110
111 int l = maxLayer;
112 for (auto vid : mEdges[v])
113 {
114 l = std::min(mLayers[vid], l);
115 }
116
117 mLayers[v] = l - 1;
118 };
119
120 while (!activeId.empty())
121 {
122 ObjectId v = activeId.front();
123
124 bool isReady = true;
125 for (auto w : mEdges[v])
126 {
127 if (!visited[w])
128 {
129 isReady = false;
130 break;
131 }
132 }
133
134 if (isReady)
135 {
136 BFS(v);
137
138 activeId.pop();
139
140 isActive[v] = false;
141 }
142 else
143 {
144 activeId.pop();
145
146 //Push v into the queue end
147 activeId.push(v);
148 }
149
150 }
151
152 int minLayler = maxLayer;
153 for (auto v : mVertices)
154 {
155 minLayler = std::min(minLayler, mLayers[v]);
156 }
157
158 for (auto v : mVertices)
159 {
160 mLayers[v] -= minLayler;
161 }
162
163 mLayerNum = maxLayer - minLayler;
164 }
165
167 {
168 ObjectId radixId = Object::baseId();
169 for (auto v : mVertices)
170 {
171 radixId = std::max(v, radixId);
172 }
173
174 radixId++;
175
176 std::map<ObjectId, std::unordered_set<ObjectId>> mNewEdges(mEdges);
177
178 for (auto it : mEdges)
179 {
180 ObjectId v = it.first;
181 for(auto w : it.second)
182 {
183 int edgeLength = mLayers[w] - mLayers[v];
184
185 if (edgeLength > 1)
186 {
187 mNewEdges[v].erase(w);
188 mReverseEdges[w].erase(v);
189
190 ObjectId v0, w0;
191 //Insert new edges
192 for (int i = 0; i < edgeLength; i++)
193 {
194 v0 = i == 0 ? v : w0;
195 w0 = i == edgeLength - 1 ? w : radixId;
196
197 mVertices.insert(w0);
198
199 mLayers[w0] = mLayers[v] + i + 1;
200
201 // Add an edge (v, w).
202 mNewEdges[v0].insert(w0);
203
204 //Add a reverse edge (w, v)
205 mReverseEdges[w0].insert(v0);
206
207 radixId++;
208 }
209 }
210 }
211 }
212
213 mEdges = mNewEdges;
214 }
215
216 struct WNode
217 {
219 float weight;
220 };
221
223 {
224 std::vector<std::vector<WNode>> weightedNodes(mLayerNum);
225
226 auto compare_vertex = [=](WNode n0, WNode n1) -> bool
227 {
228 return n0.weight < n1.weight;
229 };
230
231 //Initialize weighted nodes and the x-coordinates for all vertices
232 for(auto v : mVertices)
233 {
234 WNode ln = { v, 1.0f };
235
236 int layer = mLayers[v];
237
238 mXCoordinate[v] = weightedNodes[layer].size();
239 weightedNodes[layer].push_back(ln);
240 }
241
242 for (size_t t = 0; t < mIterNum; t++)
243 {
244 //Reorder each layer from layer i to i + 1
245 for (size_t l = 1; l < weightedNodes.size(); l++)
246 {
247 for (size_t i = 0; i < weightedNodes[l].size(); i++)
248 {
249 float sum = 0.0f;
250 ObjectId v = weightedNodes[l][i].id;
251 for(auto w : mReverseEdges[v])
252 {
253 sum += mXCoordinate[w];
254 }
255
256 weightedNodes[l][i] = { v, sum / mReverseEdges[v].size() };
257 }
258
259 std::sort(weightedNodes[l].begin(), weightedNodes[l].end(), compare_vertex);
260
261 for (size_t i = 0; i < weightedNodes[l].size(); i++)
262 {
263 ObjectId v = weightedNodes[l][i].id;
264
265 mXCoordinate[v] = i;
266 }
267 }
268
269 //Reorder each layer from layer i + 1 to i
270 for (size_t l = mLayerNum - 2; l < mLayerNum; l--)
271 {
272 for (size_t i = 0; i < weightedNodes[l].size(); i++)
273 {
274 float sum = 0.0f;
275 ObjectId v = weightedNodes[l][i].id;
276 for(auto w : mEdges[v])
277 {
278 sum += mXCoordinate[w];
279 }
280
281 weightedNodes[l][i] = { v, sum / mEdges[v].size() };
282 }
283
284 std::sort(weightedNodes[l].begin(), weightedNodes[l].end(), compare_vertex);
285
286 for (size_t i = 0; i < weightedNodes[l].size(); i++)
287 {
288 ObjectId v = weightedNodes[l][i].id;
289
290 mXCoordinate[v] = i;
291 }
292 }
293 }
294
295 mNodeLayers.resize(mLayerNum);
296
297 //Construct layers
298 for (size_t l = 0; l < weightedNodes.size(); l++)
299 {
300 for(auto n : weightedNodes[l])
301 {
302 mNodeLayers[l].push_back(n.id);
303 }
304 }
305
306 for (size_t l = 0; l < weightedNodes.size(); l++)
307 {
308 weightedNodes[l].clear();
309 }
310
311 weightedNodes.clear();
312 }
313}
std::set< ObjectId > OtherVertices
std::map< ObjectId, std::unordered_set< ObjectId > > mEdges
std::map< ObjectId, int > mXCoordinate
DirectedAcyclicGraph * pDAG
std::vector< std::vector< ObjectId > > mNodeLayers
std::map< ObjectId, int > mLayers
std::set< ObjectId > mVertices
AutoLayoutDAG(DirectedAcyclicGraph *dag)
std::vector< ObjectId > & layer(size_t l)
std::map< ObjectId, std::unordered_set< ObjectId > > mReverseEdges
Graph class represents a directed graph.
static ObjectId baseId()
Base Id.
Definition Object.cpp:46
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
void BFS(Node *node, NodeList &list, std::map< ObjectId, bool > &visited)
uint32_t ObjectId
Definition Object.h:110