Created
April 9, 2025 02:45
-
-
Save steveroush/3e8548bd185161021f231b1701022fbd to your computer and use it in GitHub Desktop.
clusterEdges.gvpr - create edges to/from clusters in dot (Graphviz) graphs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************** | |
see help below | |
********************************************************************/ | |
BEGIN{ | |
graph_t tmpG, aGraph, Root; //, Cluster[]; | |
edge_t newE; | |
node_t aNode, tNode, hNode; | |
graph_t tailCluster, headCluster; | |
int i, Gcnt; | |
string BB[]; | |
string help; | |
//////////////// help ///////////////////////////////////////////// | |
// *INDENT-OFF* turn off pretty-printing, there is a string-related bug in astyle | |
help="clusterEdges.gvpr - creates edges to/from clusters for dot graphs | |
clusterEdges.gvpr requires 2 input graphs | |
- the 1st is the graph without the desires edges to/from clusters | |
to get the desired layout, invisible edges may be required | |
- the 2nd is a pdeudo graph, consisting solely of edges to/from clusters | |
Arguments: | |
none | |
Usage examples: | |
dot myfile.gv |gvpr -f cluster2clusterEdges.gvpr|neato -n2 -Tpng -o myfile.png | |
"; // *INDENT-ON* NOTE: place on line with end-of-string | |
//////////////////////////////////////////////////////////////////////////// | |
node_t makeOverlay(graph_t Cluster, graph_t bigG){ | |
string newName, newPos; | |
double MinX,MinY,MaxX,MaxY, newX, newY; | |
newName=(string)Cluster.name + "_overlay"; | |
print("// makeOverlay : ", Cluster.name," ",BB[Cluster.name]); | |
aNode=isNode(bigG,newName); | |
if (aNode==NULL){ | |
aNode=node(bigG, newName); | |
aNode.shape="rect"; | |
sscanf (BB[Cluster.name], "%lf,%lf,%lf,%lf", &MinX, &MinY, &MaxX, &MaxY); | |
newX=MinX+(MaxX-MinX)/2; | |
newY=MinY+(MaxY-MinY)/2; | |
newPos=(string)newX +","+(string)newY; | |
aNode.pos=newPos; | |
aNode.Xbb=BB[Cluster.name]; | |
aNode.width=(MaxX-MinX)/72.; | |
aNode.height=(MaxY-MinY)/72.; | |
aNode.label=""; | |
aNode.peripheries="0"; | |
//aNode.style="filled"; // turn on for testing | |
//aNode.fillcolor="#ff000022"; // turn on for testing | |
} | |
return aNode; | |
} | |
graph_t graphTraverse(graph_t thisG) { | |
for (aGraph = fstsubg(thisG); aGraph; aGraph = nxtsubg(aGraph)) { | |
if (match(aGraph.name,"cluster")==0 || (hasAttr(aGraph, "cluster") && aGraph.cluster=="true")){ | |
print ("// CLUSTER ",aGraph.name, " ", aGraph.bb); | |
BB[aGraph.name]=aGraph.bb; | |
} | |
aGraph = graphTraverse(aGraph); | |
} | |
return thisG; | |
} // end of graphTraverse | |
Gcnt=0; | |
} | |
BEG_G { | |
Root=$G; | |
Gcnt++; | |
if (Gcnt==1){ | |
tmpG=cloneG($G,""); | |
graphTraverse($G); | |
} | |
} | |
E[Gcnt==2]{ | |
if (isNode(tmpG, $.tail.name)==NULL){ | |
tailCluster=subg(tmpG, $.tail.name); | |
print("// tail: ", tailCluster.name," ", BB[tailCluster.name]); | |
tNode=makeOverlay(tailCluster, tmpG); | |
}else{ | |
tNode=node(tmpG, $.tail.name); | |
} | |
if (isNode(tmpG, $.head.name)==NULL){ | |
headCluster=subg(tmpG, $.head.name); | |
hNode=makeOverlay(headCluster, tmpG); | |
}else{ | |
hNode=node(tmpG, $.head.name); | |
} | |
newE=edge_sg(tmpG, tNode, hNode, ""); | |
copyA($, newE); | |
newE.pos=""; | |
} | |
END_G{ | |
if (Gcnt==2){ | |
write(tmpG); | |
} | |
} | |
/********************* Demo Input ********************** | |
graph G { | |
e | |
subgraph clusterA { | |
a -- b; | |
subgraph clusterC { | |
C -- D; | |
} | |
} | |
subgraph clusterB { | |
d -- f | |
} | |
d -- D | |
} | |
graph cc{ | |
e -- clusterB | |
clusterC -- clusterB | |
} | |
**********************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment