Merging graphs in Graphviz









up vote
1
down vote

favorite












I have a collection of digraphs encoded in DOT language, and i want to merge them into a single digraph where nodes with the same name in different input graphs are merged together.



For example given the following files:



1.dot:



digraph 
A -> B
A -> C



2.dot:



digraph 
D -> E
E -> F



3.dot:



digraph 
D -> G
G -> A



I would like to obtain the following result.dot:



digraph 
subgraph
A -> B
A -> C

subgraph
D -> E
E -> F

subgraph
D -> G
G -> A





I tried to use gvpack but it renames duplicate nodes.



> gvpack -u 1.dot 2.dot 3.dot
Warning: node D in graph[2] %15 already defined
Some nodes will be renamed.
digraph root
node [label="N"];

node [label="N"];
A -> B;
A -> C;


node [label="N"];
D -> E;
E -> F;


node [label="N"];
D_gv1 -> G;
G -> A_gv1;




I found a similar question on SO that suggest using sed to rename the renamed nodes, but that doesn't seem very clean.



Is there a way to merge the graphs the way i would like them?










share|improve this question

























    up vote
    1
    down vote

    favorite












    I have a collection of digraphs encoded in DOT language, and i want to merge them into a single digraph where nodes with the same name in different input graphs are merged together.



    For example given the following files:



    1.dot:



    digraph 
    A -> B
    A -> C



    2.dot:



    digraph 
    D -> E
    E -> F



    3.dot:



    digraph 
    D -> G
    G -> A



    I would like to obtain the following result.dot:



    digraph 
    subgraph
    A -> B
    A -> C

    subgraph
    D -> E
    E -> F

    subgraph
    D -> G
    G -> A





    I tried to use gvpack but it renames duplicate nodes.



    > gvpack -u 1.dot 2.dot 3.dot
    Warning: node D in graph[2] %15 already defined
    Some nodes will be renamed.
    digraph root
    node [label="N"];

    node [label="N"];
    A -> B;
    A -> C;


    node [label="N"];
    D -> E;
    E -> F;


    node [label="N"];
    D_gv1 -> G;
    G -> A_gv1;




    I found a similar question on SO that suggest using sed to rename the renamed nodes, but that doesn't seem very clean.



    Is there a way to merge the graphs the way i would like them?










    share|improve this question























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I have a collection of digraphs encoded in DOT language, and i want to merge them into a single digraph where nodes with the same name in different input graphs are merged together.



      For example given the following files:



      1.dot:



      digraph 
      A -> B
      A -> C



      2.dot:



      digraph 
      D -> E
      E -> F



      3.dot:



      digraph 
      D -> G
      G -> A



      I would like to obtain the following result.dot:



      digraph 
      subgraph
      A -> B
      A -> C

      subgraph
      D -> E
      E -> F

      subgraph
      D -> G
      G -> A





      I tried to use gvpack but it renames duplicate nodes.



      > gvpack -u 1.dot 2.dot 3.dot
      Warning: node D in graph[2] %15 already defined
      Some nodes will be renamed.
      digraph root
      node [label="N"];

      node [label="N"];
      A -> B;
      A -> C;


      node [label="N"];
      D -> E;
      E -> F;


      node [label="N"];
      D_gv1 -> G;
      G -> A_gv1;




      I found a similar question on SO that suggest using sed to rename the renamed nodes, but that doesn't seem very clean.



      Is there a way to merge the graphs the way i would like them?










      share|improve this question













      I have a collection of digraphs encoded in DOT language, and i want to merge them into a single digraph where nodes with the same name in different input graphs are merged together.



      For example given the following files:



      1.dot:



      digraph 
      A -> B
      A -> C



      2.dot:



      digraph 
      D -> E
      E -> F



      3.dot:



      digraph 
      D -> G
      G -> A



      I would like to obtain the following result.dot:



      digraph 
      subgraph
      A -> B
      A -> C

      subgraph
      D -> E
      E -> F

      subgraph
      D -> G
      G -> A





      I tried to use gvpack but it renames duplicate nodes.



      > gvpack -u 1.dot 2.dot 3.dot
      Warning: node D in graph[2] %15 already defined
      Some nodes will be renamed.
      digraph root
      node [label="N"];

      node [label="N"];
      A -> B;
      A -> C;


      node [label="N"];
      D -> E;
      E -> F;


      node [label="N"];
      D_gv1 -> G;
      G -> A_gv1;




      I found a similar question on SO that suggest using sed to rename the renamed nodes, but that doesn't seem very clean.



      Is there a way to merge the graphs the way i would like them?







      graphviz dot






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 8 at 6:32









      Gauthier

      2,3071822




      2,3071822






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          2
          down vote













          For exactly the situation you are describing, using the sample files you provide, there is a very simple answer using m4 - a standard GNU Linux tool that should be installed by default in most distributions.



          Create a file merge123.m4 with this content:



          digraph 123 
          define(`digraph',`subgraph')
          include(1.dot)
          include(2.dot)
          include(3.dot)



          and execute it with the command



          m4 merge123.m4 > 123.dot


          and the resulting 123.dot file will be



          digraph 123 

          subgraph
          A -> B
          A -> C


          subgraph
          D -> E
          E -> F


          subgraph
          D -> G
          G -> A





          If you don't like the empty lines, close each line in the script with dnl (the builtin dnl stands for “Discard to Next Line”:), for example



          include(1.dot)dnl


          m4 is extremely useful as it adds features to graphviz that are really helpful for more involved projects; see also this SO question.



          EDITED to answer the question in the comment:



          If you need to include files and don't know their number and names, you have (at least) two options:



          1) If the number of files is rather small and you know all names that they could possibly have, you can sinclude() them all:



          digraph 123 
          define(`digraph',`subgraph')
          sinclude(1.dot)
          sinclude(2.dot)
          sinclude(3.dot)
          sinclude(4.dot)
          sinclude(5.dot)



          m4 will only include the files that actually exist, and not complain about the missing ones (the s means "silent").



          2) If you produce a larger number of.dot files with unpredictable names, you will need to do some pre-processing. Create a shell script include.sh similar to this one



          #!/bin/sh
          # get *.dot files (or any pattern you like) into one place
          ls *.dot > files.txt
          # bring them into a format m4 likes
          awk 'print "include(" $1 ")" "dnl"' files.txt > includes.txt
          #done


          includes.txt now provides m4 with the necessary information:



          include(1.dot)dnl
          include(2.dot)dnl
          include(3.dot)dnl


          Now modify your merge.m4 file, enabling it to make use of the file list provided (I'm adding dnl here to avoid lots of empty space in the resulting merged file):



          ### merge dot files
          digraph 123
          define(`digraph',`subgraph')dnl
          syscmd(`./include.sh')dnl
          include(`includes.txt')dnl



          In order to keep the resulting file separate from the input files, better use a different extension when merging:



          m4 merge.m4 > merged.gv


          which now looks like



          ### merge dot files
          digraph 123
          subgraph
          A -> B
          A -> C

          subgraph
          D -> E
          E -> F

          subgraph
          D -> G
          G -> A







          share|improve this answer






















          • Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
            – Gauthier
            Nov 9 at 3:00






          • 1




            see edits in my original answer
            – vaettchen
            Nov 10 at 3:35

















          up vote
          0
          down vote













          If it's really just a minor edit of the input files joined, then perl is a natural fit:



          use strict;
          sub main
          local $/ = undef;
          print "digraph n";
          for my $f (@ARGV)
          open(F, $f) or die $!;
          my $text = <F>;
          close(F);
          $text =~ s/digraph/subgraph/;
          $text =~s/^/ /mg;
          print $text;

          print "n";


          main;


          Then



          $ perl merge.pl 1.dot 2.dot 3.dot
          digraph
          subgraph
          A -> B
          A -> C

          subgraph
          D -> E
          E -> F

          subgraph
          D -> G
          G -> A







          share|improve this answer



























            up vote
            0
            down vote



            accepted










            I ended up using a Java library to perform the merge, and much more!



            With the library i could easily tap into the data structure, change nodes if need be, and add attributes to the graph.



            A quick example in Kotlin:



            // prepare root graph and set direction
            val wamap = mutGraph("wamap")
            .setDirected(true)
            wamap.graphAttrs().add(RankDir.LEFT_TO_RIGHT)

            // add subgraphs from the content of .gv files from disk
            Files.walk(Paths.get("D:\src\work\Wamap"), 1)
            .filter Files.isRegularFile(it)
            .filter it.fileName.toString().endsWith(".gv")
            .map Parser.read(it.toFile())
            .forEach it.addTo(wamap)

            // normalize node names to lowercase, to ensure nodes with same name are the same node
            wamap.graphs()
            .flatMap it.nodes()
            .forEach it.setName(it.name().toString().toLowerCase())

            // output as file, but also render the image directly with all the possible Graphviz layout engines
            File("out/wamap.gv").writeText(wamap.toString())
            Engine.values()
            .forEach engine ->
            Graphviz.fromGraph(wamap).engine(engine).render(Format.PNG).toFile(File("out/wamap-$engine.png"))






            share|improve this answer




















              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202550%2fmerging-graphs-in-graphviz%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              2
              down vote













              For exactly the situation you are describing, using the sample files you provide, there is a very simple answer using m4 - a standard GNU Linux tool that should be installed by default in most distributions.



              Create a file merge123.m4 with this content:



              digraph 123 
              define(`digraph',`subgraph')
              include(1.dot)
              include(2.dot)
              include(3.dot)



              and execute it with the command



              m4 merge123.m4 > 123.dot


              and the resulting 123.dot file will be



              digraph 123 

              subgraph
              A -> B
              A -> C


              subgraph
              D -> E
              E -> F


              subgraph
              D -> G
              G -> A





              If you don't like the empty lines, close each line in the script with dnl (the builtin dnl stands for “Discard to Next Line”:), for example



              include(1.dot)dnl


              m4 is extremely useful as it adds features to graphviz that are really helpful for more involved projects; see also this SO question.



              EDITED to answer the question in the comment:



              If you need to include files and don't know their number and names, you have (at least) two options:



              1) If the number of files is rather small and you know all names that they could possibly have, you can sinclude() them all:



              digraph 123 
              define(`digraph',`subgraph')
              sinclude(1.dot)
              sinclude(2.dot)
              sinclude(3.dot)
              sinclude(4.dot)
              sinclude(5.dot)



              m4 will only include the files that actually exist, and not complain about the missing ones (the s means "silent").



              2) If you produce a larger number of.dot files with unpredictable names, you will need to do some pre-processing. Create a shell script include.sh similar to this one



              #!/bin/sh
              # get *.dot files (or any pattern you like) into one place
              ls *.dot > files.txt
              # bring them into a format m4 likes
              awk 'print "include(" $1 ")" "dnl"' files.txt > includes.txt
              #done


              includes.txt now provides m4 with the necessary information:



              include(1.dot)dnl
              include(2.dot)dnl
              include(3.dot)dnl


              Now modify your merge.m4 file, enabling it to make use of the file list provided (I'm adding dnl here to avoid lots of empty space in the resulting merged file):



              ### merge dot files
              digraph 123
              define(`digraph',`subgraph')dnl
              syscmd(`./include.sh')dnl
              include(`includes.txt')dnl



              In order to keep the resulting file separate from the input files, better use a different extension when merging:



              m4 merge.m4 > merged.gv


              which now looks like



              ### merge dot files
              digraph 123
              subgraph
              A -> B
              A -> C

              subgraph
              D -> E
              E -> F

              subgraph
              D -> G
              G -> A







              share|improve this answer






















              • Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
                – Gauthier
                Nov 9 at 3:00






              • 1




                see edits in my original answer
                – vaettchen
                Nov 10 at 3:35














              up vote
              2
              down vote













              For exactly the situation you are describing, using the sample files you provide, there is a very simple answer using m4 - a standard GNU Linux tool that should be installed by default in most distributions.



              Create a file merge123.m4 with this content:



              digraph 123 
              define(`digraph',`subgraph')
              include(1.dot)
              include(2.dot)
              include(3.dot)



              and execute it with the command



              m4 merge123.m4 > 123.dot


              and the resulting 123.dot file will be



              digraph 123 

              subgraph
              A -> B
              A -> C


              subgraph
              D -> E
              E -> F


              subgraph
              D -> G
              G -> A





              If you don't like the empty lines, close each line in the script with dnl (the builtin dnl stands for “Discard to Next Line”:), for example



              include(1.dot)dnl


              m4 is extremely useful as it adds features to graphviz that are really helpful for more involved projects; see also this SO question.



              EDITED to answer the question in the comment:



              If you need to include files and don't know their number and names, you have (at least) two options:



              1) If the number of files is rather small and you know all names that they could possibly have, you can sinclude() them all:



              digraph 123 
              define(`digraph',`subgraph')
              sinclude(1.dot)
              sinclude(2.dot)
              sinclude(3.dot)
              sinclude(4.dot)
              sinclude(5.dot)



              m4 will only include the files that actually exist, and not complain about the missing ones (the s means "silent").



              2) If you produce a larger number of.dot files with unpredictable names, you will need to do some pre-processing. Create a shell script include.sh similar to this one



              #!/bin/sh
              # get *.dot files (or any pattern you like) into one place
              ls *.dot > files.txt
              # bring them into a format m4 likes
              awk 'print "include(" $1 ")" "dnl"' files.txt > includes.txt
              #done


              includes.txt now provides m4 with the necessary information:



              include(1.dot)dnl
              include(2.dot)dnl
              include(3.dot)dnl


              Now modify your merge.m4 file, enabling it to make use of the file list provided (I'm adding dnl here to avoid lots of empty space in the resulting merged file):



              ### merge dot files
              digraph 123
              define(`digraph',`subgraph')dnl
              syscmd(`./include.sh')dnl
              include(`includes.txt')dnl



              In order to keep the resulting file separate from the input files, better use a different extension when merging:



              m4 merge.m4 > merged.gv


              which now looks like



              ### merge dot files
              digraph 123
              subgraph
              A -> B
              A -> C

              subgraph
              D -> E
              E -> F

              subgraph
              D -> G
              G -> A







              share|improve this answer






















              • Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
                – Gauthier
                Nov 9 at 3:00






              • 1




                see edits in my original answer
                – vaettchen
                Nov 10 at 3:35












              up vote
              2
              down vote










              up vote
              2
              down vote









              For exactly the situation you are describing, using the sample files you provide, there is a very simple answer using m4 - a standard GNU Linux tool that should be installed by default in most distributions.



              Create a file merge123.m4 with this content:



              digraph 123 
              define(`digraph',`subgraph')
              include(1.dot)
              include(2.dot)
              include(3.dot)



              and execute it with the command



              m4 merge123.m4 > 123.dot


              and the resulting 123.dot file will be



              digraph 123 

              subgraph
              A -> B
              A -> C


              subgraph
              D -> E
              E -> F


              subgraph
              D -> G
              G -> A





              If you don't like the empty lines, close each line in the script with dnl (the builtin dnl stands for “Discard to Next Line”:), for example



              include(1.dot)dnl


              m4 is extremely useful as it adds features to graphviz that are really helpful for more involved projects; see also this SO question.



              EDITED to answer the question in the comment:



              If you need to include files and don't know their number and names, you have (at least) two options:



              1) If the number of files is rather small and you know all names that they could possibly have, you can sinclude() them all:



              digraph 123 
              define(`digraph',`subgraph')
              sinclude(1.dot)
              sinclude(2.dot)
              sinclude(3.dot)
              sinclude(4.dot)
              sinclude(5.dot)



              m4 will only include the files that actually exist, and not complain about the missing ones (the s means "silent").



              2) If you produce a larger number of.dot files with unpredictable names, you will need to do some pre-processing. Create a shell script include.sh similar to this one



              #!/bin/sh
              # get *.dot files (or any pattern you like) into one place
              ls *.dot > files.txt
              # bring them into a format m4 likes
              awk 'print "include(" $1 ")" "dnl"' files.txt > includes.txt
              #done


              includes.txt now provides m4 with the necessary information:



              include(1.dot)dnl
              include(2.dot)dnl
              include(3.dot)dnl


              Now modify your merge.m4 file, enabling it to make use of the file list provided (I'm adding dnl here to avoid lots of empty space in the resulting merged file):



              ### merge dot files
              digraph 123
              define(`digraph',`subgraph')dnl
              syscmd(`./include.sh')dnl
              include(`includes.txt')dnl



              In order to keep the resulting file separate from the input files, better use a different extension when merging:



              m4 merge.m4 > merged.gv


              which now looks like



              ### merge dot files
              digraph 123
              subgraph
              A -> B
              A -> C

              subgraph
              D -> E
              E -> F

              subgraph
              D -> G
              G -> A







              share|improve this answer














              For exactly the situation you are describing, using the sample files you provide, there is a very simple answer using m4 - a standard GNU Linux tool that should be installed by default in most distributions.



              Create a file merge123.m4 with this content:



              digraph 123 
              define(`digraph',`subgraph')
              include(1.dot)
              include(2.dot)
              include(3.dot)



              and execute it with the command



              m4 merge123.m4 > 123.dot


              and the resulting 123.dot file will be



              digraph 123 

              subgraph
              A -> B
              A -> C


              subgraph
              D -> E
              E -> F


              subgraph
              D -> G
              G -> A





              If you don't like the empty lines, close each line in the script with dnl (the builtin dnl stands for “Discard to Next Line”:), for example



              include(1.dot)dnl


              m4 is extremely useful as it adds features to graphviz that are really helpful for more involved projects; see also this SO question.



              EDITED to answer the question in the comment:



              If you need to include files and don't know their number and names, you have (at least) two options:



              1) If the number of files is rather small and you know all names that they could possibly have, you can sinclude() them all:



              digraph 123 
              define(`digraph',`subgraph')
              sinclude(1.dot)
              sinclude(2.dot)
              sinclude(3.dot)
              sinclude(4.dot)
              sinclude(5.dot)



              m4 will only include the files that actually exist, and not complain about the missing ones (the s means "silent").



              2) If you produce a larger number of.dot files with unpredictable names, you will need to do some pre-processing. Create a shell script include.sh similar to this one



              #!/bin/sh
              # get *.dot files (or any pattern you like) into one place
              ls *.dot > files.txt
              # bring them into a format m4 likes
              awk 'print "include(" $1 ")" "dnl"' files.txt > includes.txt
              #done


              includes.txt now provides m4 with the necessary information:



              include(1.dot)dnl
              include(2.dot)dnl
              include(3.dot)dnl


              Now modify your merge.m4 file, enabling it to make use of the file list provided (I'm adding dnl here to avoid lots of empty space in the resulting merged file):



              ### merge dot files
              digraph 123
              define(`digraph',`subgraph')dnl
              syscmd(`./include.sh')dnl
              include(`includes.txt')dnl



              In order to keep the resulting file separate from the input files, better use a different extension when merging:



              m4 merge.m4 > merged.gv


              which now looks like



              ### merge dot files
              digraph 123
              subgraph
              A -> B
              A -> C

              subgraph
              D -> E
              E -> F

              subgraph
              D -> G
              G -> A








              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Nov 10 at 5:18

























              answered Nov 8 at 8:50









              vaettchen

              4,9751332




              4,9751332











              • Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
                – Gauthier
                Nov 9 at 3:00






              • 1




                see edits in my original answer
                – vaettchen
                Nov 10 at 3:35
















              • Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
                – Gauthier
                Nov 9 at 3:00






              • 1




                see edits in my original answer
                – vaettchen
                Nov 10 at 3:35















              Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
              – Gauthier
              Nov 9 at 3:00




              Thanks, that's interesting. Is there a way to use m4 if the number of input files as well as their names is variable?
              – Gauthier
              Nov 9 at 3:00




              1




              1




              see edits in my original answer
              – vaettchen
              Nov 10 at 3:35




              see edits in my original answer
              – vaettchen
              Nov 10 at 3:35












              up vote
              0
              down vote













              If it's really just a minor edit of the input files joined, then perl is a natural fit:



              use strict;
              sub main
              local $/ = undef;
              print "digraph n";
              for my $f (@ARGV)
              open(F, $f) or die $!;
              my $text = <F>;
              close(F);
              $text =~ s/digraph/subgraph/;
              $text =~s/^/ /mg;
              print $text;

              print "n";


              main;


              Then



              $ perl merge.pl 1.dot 2.dot 3.dot
              digraph
              subgraph
              A -> B
              A -> C

              subgraph
              D -> E
              E -> F

              subgraph
              D -> G
              G -> A







              share|improve this answer
























                up vote
                0
                down vote













                If it's really just a minor edit of the input files joined, then perl is a natural fit:



                use strict;
                sub main
                local $/ = undef;
                print "digraph n";
                for my $f (@ARGV)
                open(F, $f) or die $!;
                my $text = <F>;
                close(F);
                $text =~ s/digraph/subgraph/;
                $text =~s/^/ /mg;
                print $text;

                print "n";


                main;


                Then



                $ perl merge.pl 1.dot 2.dot 3.dot
                digraph
                subgraph
                A -> B
                A -> C

                subgraph
                D -> E
                E -> F

                subgraph
                D -> G
                G -> A







                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  If it's really just a minor edit of the input files joined, then perl is a natural fit:



                  use strict;
                  sub main
                  local $/ = undef;
                  print "digraph n";
                  for my $f (@ARGV)
                  open(F, $f) or die $!;
                  my $text = <F>;
                  close(F);
                  $text =~ s/digraph/subgraph/;
                  $text =~s/^/ /mg;
                  print $text;

                  print "n";


                  main;


                  Then



                  $ perl merge.pl 1.dot 2.dot 3.dot
                  digraph
                  subgraph
                  A -> B
                  A -> C

                  subgraph
                  D -> E
                  E -> F

                  subgraph
                  D -> G
                  G -> A







                  share|improve this answer












                  If it's really just a minor edit of the input files joined, then perl is a natural fit:



                  use strict;
                  sub main
                  local $/ = undef;
                  print "digraph n";
                  for my $f (@ARGV)
                  open(F, $f) or die $!;
                  my $text = <F>;
                  close(F);
                  $text =~ s/digraph/subgraph/;
                  $text =~s/^/ /mg;
                  print $text;

                  print "n";


                  main;


                  Then



                  $ perl merge.pl 1.dot 2.dot 3.dot
                  digraph
                  subgraph
                  A -> B
                  A -> C

                  subgraph
                  D -> E
                  E -> F

                  subgraph
                  D -> G
                  G -> A








                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 8 at 6:47









                  Gene

                  37.4k44273




                  37.4k44273




















                      up vote
                      0
                      down vote



                      accepted










                      I ended up using a Java library to perform the merge, and much more!



                      With the library i could easily tap into the data structure, change nodes if need be, and add attributes to the graph.



                      A quick example in Kotlin:



                      // prepare root graph and set direction
                      val wamap = mutGraph("wamap")
                      .setDirected(true)
                      wamap.graphAttrs().add(RankDir.LEFT_TO_RIGHT)

                      // add subgraphs from the content of .gv files from disk
                      Files.walk(Paths.get("D:\src\work\Wamap"), 1)
                      .filter Files.isRegularFile(it)
                      .filter it.fileName.toString().endsWith(".gv")
                      .map Parser.read(it.toFile())
                      .forEach it.addTo(wamap)

                      // normalize node names to lowercase, to ensure nodes with same name are the same node
                      wamap.graphs()
                      .flatMap it.nodes()
                      .forEach it.setName(it.name().toString().toLowerCase())

                      // output as file, but also render the image directly with all the possible Graphviz layout engines
                      File("out/wamap.gv").writeText(wamap.toString())
                      Engine.values()
                      .forEach engine ->
                      Graphviz.fromGraph(wamap).engine(engine).render(Format.PNG).toFile(File("out/wamap-$engine.png"))






                      share|improve this answer
























                        up vote
                        0
                        down vote



                        accepted










                        I ended up using a Java library to perform the merge, and much more!



                        With the library i could easily tap into the data structure, change nodes if need be, and add attributes to the graph.



                        A quick example in Kotlin:



                        // prepare root graph and set direction
                        val wamap = mutGraph("wamap")
                        .setDirected(true)
                        wamap.graphAttrs().add(RankDir.LEFT_TO_RIGHT)

                        // add subgraphs from the content of .gv files from disk
                        Files.walk(Paths.get("D:\src\work\Wamap"), 1)
                        .filter Files.isRegularFile(it)
                        .filter it.fileName.toString().endsWith(".gv")
                        .map Parser.read(it.toFile())
                        .forEach it.addTo(wamap)

                        // normalize node names to lowercase, to ensure nodes with same name are the same node
                        wamap.graphs()
                        .flatMap it.nodes()
                        .forEach it.setName(it.name().toString().toLowerCase())

                        // output as file, but also render the image directly with all the possible Graphviz layout engines
                        File("out/wamap.gv").writeText(wamap.toString())
                        Engine.values()
                        .forEach engine ->
                        Graphviz.fromGraph(wamap).engine(engine).render(Format.PNG).toFile(File("out/wamap-$engine.png"))






                        share|improve this answer






















                          up vote
                          0
                          down vote



                          accepted







                          up vote
                          0
                          down vote



                          accepted






                          I ended up using a Java library to perform the merge, and much more!



                          With the library i could easily tap into the data structure, change nodes if need be, and add attributes to the graph.



                          A quick example in Kotlin:



                          // prepare root graph and set direction
                          val wamap = mutGraph("wamap")
                          .setDirected(true)
                          wamap.graphAttrs().add(RankDir.LEFT_TO_RIGHT)

                          // add subgraphs from the content of .gv files from disk
                          Files.walk(Paths.get("D:\src\work\Wamap"), 1)
                          .filter Files.isRegularFile(it)
                          .filter it.fileName.toString().endsWith(".gv")
                          .map Parser.read(it.toFile())
                          .forEach it.addTo(wamap)

                          // normalize node names to lowercase, to ensure nodes with same name are the same node
                          wamap.graphs()
                          .flatMap it.nodes()
                          .forEach it.setName(it.name().toString().toLowerCase())

                          // output as file, but also render the image directly with all the possible Graphviz layout engines
                          File("out/wamap.gv").writeText(wamap.toString())
                          Engine.values()
                          .forEach engine ->
                          Graphviz.fromGraph(wamap).engine(engine).render(Format.PNG).toFile(File("out/wamap-$engine.png"))






                          share|improve this answer












                          I ended up using a Java library to perform the merge, and much more!



                          With the library i could easily tap into the data structure, change nodes if need be, and add attributes to the graph.



                          A quick example in Kotlin:



                          // prepare root graph and set direction
                          val wamap = mutGraph("wamap")
                          .setDirected(true)
                          wamap.graphAttrs().add(RankDir.LEFT_TO_RIGHT)

                          // add subgraphs from the content of .gv files from disk
                          Files.walk(Paths.get("D:\src\work\Wamap"), 1)
                          .filter Files.isRegularFile(it)
                          .filter it.fileName.toString().endsWith(".gv")
                          .map Parser.read(it.toFile())
                          .forEach it.addTo(wamap)

                          // normalize node names to lowercase, to ensure nodes with same name are the same node
                          wamap.graphs()
                          .flatMap it.nodes()
                          .forEach it.setName(it.name().toString().toLowerCase())

                          // output as file, but also render the image directly with all the possible Graphviz layout engines
                          File("out/wamap.gv").writeText(wamap.toString())
                          Engine.values()
                          .forEach engine ->
                          Graphviz.fromGraph(wamap).engine(engine).render(Format.PNG).toFile(File("out/wamap-$engine.png"))







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 14 at 6:56









                          Gauthier

                          2,3071822




                          2,3071822



























                              draft saved

                              draft discarded
















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202550%2fmerging-graphs-in-graphviz%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

                              Syphilis

                              Darth Vader #20