6 * $Date: 2012-07-05 16:45:20 +0200 (Do, 05. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of class GalaxyMultilevelBuilder.
12 * \author Martin Gronemann
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
43 #include "GalaxyMultilevel.h"
45 #include "FastUtils.h"
46 #include <ogdf/basic/Array.h>
51 void GalaxyMultilevelBuilder::computeSystemMass()
54 forall_nodes(v
, *m_pGraph
)
56 m_nodeState
[v
].sysMass
= (*m_pNodeInfo
)[v
].mass
;
57 m_nodeState
[v
].label
= 0;
58 m_nodeState
[v
].lastVisitor
= v
;
61 forall_nodes(v
, *m_pGraph
)
66 m_nodeState
[v
].sysMass
+= (*m_pNodeInfo
)[adj
->twinNode()].mass
;
70 m_nodeState
[v
].sysMass
*= m_pGraph
->numberOfNodes() ;
75 void swap(ogdf::GalaxyMultilevelBuilder::NodeOrderInfo
& a
, ogdf::GalaxyMultilevelBuilder::NodeOrderInfo
& b
)
77 ogdf::GalaxyMultilevelBuilder::NodeOrderInfo t
= a
;
83 void GalaxyMultilevelBuilder::sortNodesBySystemMass()
87 m_pRandomSet
= new RandomNodeSet(*m_pGraph
);
88 for (i
=0;i
<m_pGraph
->numberOfNodes();i
++)
90 v
= m_pRandomSet
->chooseNode();
91 m_pRandomSet
->removeNode(v
);
92 m_nodeMassOrder
[i
].theNode
= v
;
96 std::sort(m_nodeMassOrder
, m_nodeMassOrder
+(m_pGraph
->numberOfNodes()), NodeMassComparer( m_nodeState
));
100 void GalaxyMultilevelBuilder::labelSystem(node u
, node v
, int d
, float df
)
107 node w
= adj
->twinNode();
108 // this node may have been labeled before but its closer to the current sun
109 if (m_nodeState
[w
].label
< d
)
111 float currDistFromSun
= (*m_pEdgeInfo
)[adj
->theEdge()].length
+ df
/*+ (*m_pNodeInfo)[w].radius*/;
112 // check if we relabeling by a new sun
113 if (m_nodeState
[w
].lastVisitor
!= u
)
115 // maybe this node has never been labeled
116 m_nodeState
[w
].lastVisitor
= u
;
117 m_nodeState
[w
].edgeLengthFromSun
= currDistFromSun
;
119 // finally relabel it
120 m_nodeState
[w
].edgeLengthFromSun
= min(m_nodeState
[w
].edgeLengthFromSun
, currDistFromSun
);
121 m_nodeState
[w
].label
= d
;
122 labelSystem(u
, w
, d
-1, currDistFromSun
/*+(*m_pNodeInfo)[w].radius*/);
129 void GalaxyMultilevelBuilder::labelSystem()
131 m_sunNodeList
.clear();
133 forall_nodes(v
, *m_pGraph
)
135 m_nodeState
[v
].sysMass
= 0;
136 m_nodeState
[v
].label
= 0;
137 m_nodeState
[v
].lastVisitor
= v
;
140 for (int i
=0; i
< m_pGraph
->numberOfNodes(); i
++)
142 v
= m_nodeMassOrder
[i
].theNode
;
143 if (m_nodeState
[v
].label
== 0)
145 m_sunNodeList
.pushBack(v
);
146 m_nodeState
[v
].label
= (m_dist
+1);
147 m_nodeState
[v
].edgeLengthFromSun
= 0.0;//(*m_pNodeInfo)[v].radius;
148 labelSystem(v
, v
, m_dist
, m_nodeState
[v
].edgeLengthFromSun
);
154 GalaxyMultilevel
* GalaxyMultilevelBuilder::build(GalaxyMultilevel
* pMultiLevel
)
157 m_pGraph
= pMultiLevel
->m_pGraph
;
158 m_pNodeInfo
= pMultiLevel
->m_pNodeInfo
;
159 m_pEdgeInfo
= pMultiLevel
->m_pEdgeInfo
;
160 m_nodeMassOrder
= (NodeOrderInfo
*)MALLOC_16(sizeof(NodeOrderInfo
)*m_pGraph
->numberOfNodes());
161 m_nodeState
.init(*m_pGraph
);
163 this->computeSystemMass();
164 this->sortNodesBySystemMass();
166 GalaxyMultilevel
* pMultiLevelResult
= new GalaxyMultilevel(pMultiLevel
);
167 this->createResult(pMultiLevelResult
);;
169 FREE_16(m_nodeMassOrder
);
171 return pMultiLevelResult
;
175 void GalaxyMultilevelBuilder::createResult(GalaxyMultilevel
* pMultiLevelResult
)
177 pMultiLevelResult
->m_pGraph
= new Graph();
178 m_pGraphResult
= pMultiLevelResult
->m_pGraph
;
180 NodeArray
<node
> toResultNode(*m_pGraph
, 0);
181 // create all sun nodes
182 for(List
<node
>::iterator it
= m_sunNodeList
.begin(); it
.valid(); it
++)
185 node vResult
= m_pGraphResult
->newNode();
186 toResultNode
[v
] = vResult
;
189 pMultiLevelResult
->m_pNodeInfo
= new NodeArray
<GalaxyMultilevel::LevelNodeInfo
>(*m_pGraphResult
);
190 m_pNodeInfoResult
= pMultiLevelResult
->m_pNodeInfo
;
192 // calculate the real system mass. this may not be the same as calculated before
194 forall_nodes(u
, *m_pGraphResult
)
196 (*m_pNodeInfoResult
)[u
].radius
= 0.0f
;
197 (*m_pNodeInfoResult
)[u
].mass
= 0.0f
;
199 forall_nodes(u
, *m_pGraph
)
201 node uSun
= m_nodeState
[u
].lastVisitor
;
202 node uSunResult
= toResultNode
[uSun
];
203 (*m_pNodeInfo
)[u
].parent
= uSunResult
;
204 (*m_pNodeInfoResult
)[uSunResult
].mass
+=((*m_pNodeInfo
)[u
].mass
);
205 (*m_pNodeInfoResult
)[uSunResult
].radius
= max( (*m_pNodeInfoResult
)[uSunResult
].radius
, m_nodeState
[u
].edgeLengthFromSun
);//m_nodeState[u].edgeLengthFromSun;//m_nodeState[u].edgeLengthFromSun;// max( (*m_pNodeInfoResult)[uSunResult].radius, m_nodeState[u].edgeLengthFromSun);
208 pMultiLevelResult
->m_pEdgeInfo
= new EdgeArray
<GalaxyMultilevel::LevelEdgeInfo
>(*m_pGraphResult
);
209 m_pEdgeInfoResult
= pMultiLevelResult
->m_pEdgeInfo
;
212 forall_edges(e
, *m_pGraph
)
214 node v
= e
->source();
215 node w
= e
->target();
216 node vSun
= m_nodeState
[v
].lastVisitor
;
217 node wSun
= m_nodeState
[w
].lastVisitor
;
220 node vSunResult
= toResultNode
[vSun
];
221 node wSunResult
= toResultNode
[wSun
];
222 edge eResult
= m_pGraphResult
->newEdge(vSunResult
, wSunResult
);
223 (*m_pEdgeInfoResult
)[eResult
].length
= m_nodeState
[v
].edgeLengthFromSun
+ (*m_pEdgeInfo
)[e
].length
+ m_nodeState
[w
].edgeLengthFromSun
;
227 // make fast parallel free
228 NodeArray
<node
> lastVisit(*m_pGraphResult
, 0);
230 forall_nodes(v
, *m_pGraphResult
)
234 adjEntry adj
= v
->firstAdj();
236 node w
= adj
->twinNode();
237 edge e
= adj
->theEdge();
238 adj
= adj
->cyclicSucc();
239 if (lastVisit
[w
] ==v
)
240 m_pGraphResult
->delEdge(e
);
243 } while (adj
!=v
->firstAdj());
248 } // end of namespace