Last active
May 21, 2025 14:27
-
-
Save steveroush/eb3743f0cc234339ea1b18f3c3de85f1 to your computer and use it in GitHub Desktop.
Revisions
-
steveroush revised this gist
May 21, 2025 . 1 changed file with 5 additions and 3 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ /********************************************************************************** compressCluster.gvpr - replace one or more clusters (and contents) with single node(s) see help below **********************************************************************************/ BEGIN{ @@ -11,14 +11,16 @@ BEGIN{ //////////////// help ///////////////////////////////////////////// string help=" compressCluster.gvpr - replace one or more clusters (and contents) with single node(s) can be used: - as a preprocessor, then feed output into dot or - as a postprocessor (after dot) to simplify an existing dot graph Arguments: -aCcluster_name -aCanotherCluster ...] Usage examples: gvpr -aCclusterdogs -aCclustercats -cf compressCluster.gvpr myfile.gv "; -
steveroush created this gist
May 21, 2025 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,152 @@ /********************************************************************************** compressCluster.gvpr - replace a cluster (and contents) with a single node see help below **********************************************************************************/ BEGIN{ graph_t aGraph, Root, Parent[], gList[]; node_t aNode, newNode, saveNode[]; edge_t newE; string cStr, newStr, newName[]; int i, OK, DeleteN[], DeleteG[], cName[]; //////////////// help ///////////////////////////////////////////// string help=" compressCluster.gvpr - replace a cluster (and contents) with a simple node can be used: - as a preprocessor, then feed output into dot or - as a postprocessor (after dot) to simplify an existing dot graph Arguments: -aCcluster_name ... Usage examples: gvpr -aCclusterdogs -aCclustercats -cf compressCluster.gvpr myfile.gv "; /////////////////////////////////////////////////////////////// graph_t clusterCheck(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); gList[aGraph.name]=aGraph; } aGraph = clusterCheck(aGraph); } return thisG; } // end of clusterTraverse /////////////////////////////////////////////////////////////// graph_t clusterDelete(graph_t thisG, string newname) { for (aNode=fstnode(aGraph); aNode; aNode = nxtnode_sg(aGraph, aNode)) { DeleteN[aNode]=1; newName[aNode]=newname; //print ("// old name: ", aNode.name," new name: ", newname); } for (aGraph = fstsubg(thisG); aGraph; aGraph = nxtsubg(aGraph)) { for (aNode=fstnode(aGraph); aNode; aNode = nxtnode_sg(aGraph, aNode)) { DeleteN[aNode]=1; newName[aNode]=newname; } aGraph = clusterDelete(aGraph, newname); } return thisG; } // end of clusterDelete ////////////////////////////////////////////////////////////// i=0; while (i<ARGC) { if (ARGV[i]=="C") { // -a "C clusterName ..." cName[ARGV[++i]]; } else if (ARGV[i]=="C*") { // -a "CclusterName ..." cName[substr(ARGV[i],1)]=1; } else { print(help); exit (0); } i++; } } ////////////////////////////////////////////////////////////////////// BEG_G { Root=$G; clusterCheck(Root); OK=1; for (cName[cStr]) { aGraph=gList[cStr]; if (aGraph==NULL) { printf(2, "Error: there is no cluster named %s\n", cStr); OK=0; } else { DeleteG[aGraph]=1; newStr="_COLLAPSED_" + aGraph.name; newNode=node(aGraph.parent, newStr); saveNode[newStr]=newNode; if (hasAttr(aGraph, "bgcolor")) { newNode.style="filled"; newNode.fillcolor=aGraph.bgcolor; } else { newNode.color="red"; } if (hasAttr(aGraph, "shape")) { newNode.shape=aGraph.shape; } else { newNode.shape="rect"; } if (hasAttr(aGraph, "label") && aGraph.label!="" && aGraph.label!="\G") { newNode.label=aGraph.label; } else { newNode.label=aGraph.name; } if (hasAttr(aGraph, "bb") && aGraph.bb!="") { newNode.origBB=aGraph.bb; float llx, lly, urx, ury; sscanf (aGraph.bb, "%lf,%lf,%lf,%lf", &llx, &lly, &urx, &ury); // adjust bb values to remove cluster margin newNode.pos=(string)(llx+((urx-llx)/2)) + "," + (string)(lly+((ury-lly)/2)); } clusterDelete(aGraph, newStr); } } if (OK!=1) exit(1); } //////////////////////////////////////////////////////////////////////////////////// E{ //print("// edge: ", $.name); if (DeleteN[$.tail] == 0 && DeleteN[$.head]==0) continue; // no cluster involvement, skip if (newName[$.tail] == newName[$.head]) { //print("// edge - both ends in same cluster to be deleted: ", $.name); delete(Root, $); continue; // all in cluster, just delete } //print("// fix this edge: ", $.name); if (DeleteN[$.tail] == 1) { newE=edge(saveNode[newName[$.tail]], $.head, ""); copyA($, newE); newE.label=""; newE.pos=""; //print("// adding edge: ", newE.name); //print("// deleting edge: ", $.name); delete(Root, $); } else { newE=edge($.tail, saveNode[newName[$.head]], ""); copyA($, newE); newE.label=""; newE.pos=""; //print("// deleting edge: ", $.name); delete(Root, $); } } BEG_G{ //reset traverse } N[DeleteN[$]==1] { //print("// deleting node: ", $.name); delete(Root, $); } END_G{ for (DeleteG[aGraph]) { //print("// deleting graph: ", aGraph.name); delete(Root, aGraph); } }