9
$\begingroup$

In the documentation ClosedLoopResponsesWithAPIDController, There is a very nice block diagram. I want to create my own block diagrams similar to this. I clicked on the diagram and pressed "command-shift-E" to show the underlying expression. I found the expression below. While this is explicit and reasonably easy to modify and extend, For really big graphs (which I have) it will rapidly become too difficult to manage by hand. I wonder if there is an easier way to produce such graphics? Is there a tool I just don't know about for drawing and / or automatically laying out such things?

Graph[{1, 2, 3, 4, 5, 6, 7, 8, 
        9}, {{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}, {6, 
    2}, {8, 4}, {9, 6}}, Null}, {
        EdgeLabels -> {DirectedEdge[8, 4] -> Placed[
                 Style["+", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], {1, {-0.8, 0.2}}], 
    DirectedEdge[3, 4] -> Placed[
                 Style["+", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], 0.9], 
    DirectedEdge[9, 6] -> Placed[
                 Style["+", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], {1, {-0.8, 0.2}}], 
    DirectedEdge[5, 6] -> Placed[
                 Style["+", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], 0.9], 
    DirectedEdge[6, 2] -> Placed[
                 Style["-", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], {0.965, {-0.7, 0}}], 
    DirectedEdge[1, 2] -> Placed[
                 Style["+", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], 0.9]}, 
         EdgeShapeFunction -> {}, 
         EdgeStyle -> {
             GrayLevel[0, 1]}, Epilog -> {
             Text[
               Style["u", {FontFamily -> "Helvetica", 
                   GrayLevel[0, 1], 12}], {2.5, 0.1}]}, 
  ImageSize -> 500, 
         VertexCoordinates -> {{0., 0.}, {0.7, 0.}, {1.8, 0.}, {2.9, 
     0.}, {3.9, 0.}, {5., 0.}, {5.6, 0.}, {
             2.9, 0.66}, {5., 0.66}}, VertexLabels -> {1 -> Placed[
                 Style["r", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 6 -> Placed[
                 Style["", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 9 -> Placed[
                 Style["m", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 2 -> Placed[
                 Style["", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 8 -> Placed[
                 Style["d", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 7 -> Placed[
                 Style["y", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 3 -> Placed[
                 Style["PID controller", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 4 -> Placed[
                 Style["", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center], 5 -> Placed[
                 Style["linear system", {FontFamily -> "Helvetica", 
                     GrayLevel[0, 1], 12}], Center]}, 
         VertexShapeFunction -> {
            3 -> "Square", 4 -> "Circle", 7 -> "Square", 
    5 -> "Square", 9 -> "Square", 1 -> "Square", 6 ->
              "Circle", 8 -> "Square", 2 -> "Circle"}, 
         VertexSize -> {8 -> {0.1, 0.1}, 3 -> {0.6, 0.2}, 
    2 -> {0.125, 0.125}, 1 -> {0.1, 0.1}, 9 -> {0.1, 0.1}, 
             4 -> {0.125, 0.125}, 6 -> {0.125, 0.125}, 
    5 -> {0.6, 0.2}, 7 -> {0.1, 0.1}}, 
         VertexStyle ->
   {2 -> Directive[GrayLevel[1], 
      EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]], 
    1 -> Directive[Opacity[0], EdgeForm[{}]],
    8 -> Directive[Opacity[0], EdgeForm[{}]],
    7 -> Directive[Opacity[0], EdgeForm[{}]],
    5 -> Directive[GrayLevel[1], 
      EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
    6 -> Directive[GrayLevel[1], 
      EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
    4 -> Directive[GrayLevel[1], 
      EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]],
    9 -> Directive[Opacity[0], EdgeForm[{}]],
    3 -> Directive[GrayLevel[1], 
      EdgeForm[{GrayLevel[0], AbsoluteThickness[1]}]]
    }}]
$\endgroup$
  • 2
    $\begingroup$ I think Mathematica doesn't have good graph layout algorithms that can handle this, but I may be wrong. The reason is that for this a special edge-layout algorithm is needed. I would try yEd first to see if it's orthogonal edge layout works well. If it doesn't, and I decide to do it in Mathematica, I might try to write my own layout algorithm instead of using Graph objects, but this is probably a lot of work. These are just ideas, nothing definitive. $\endgroup$ – Szabolcs Sep 4 '14 at 17:06
  • 2
    $\begingroup$ There's a good answer in the Wolfram forums tinyurl.com/q7j78kj: use "SystemModeler" to draw diagrams then import them into MMA. Of course, SM is another purchase. yEd is great, but outputs graphML. It might be feasible to write a graphML renderer in MMA. $\endgroup$ – Reb.Cabin Sep 5 '14 at 1:36
  • 1
    $\begingroup$ If you need to import back to Mma and preserve the edge layout, try saving as GML (not GraphML) from yEd. $\endgroup$ – Szabolcs Sep 5 '14 at 1:40
  • 1
    $\begingroup$ These can also be made with latex/tikz $\endgroup$ – Nasser Apr 5 '15 at 5:10
  • $\begingroup$ @Nasser I fully agree. It would be much better ... $\endgroup$ – LCarvalho Jun 30 '17 at 14:31
3
$\begingroup$

A little more summarized, but still extensive:

aL=25(*ArrowLenght*);rC=5(*RadiusCircle*);rL=34(*RectangleLenght*);
sequence={aL,2rC,aL,rL,aL,2rC,aL,rL,aL,2rC,aL};
accSequence=Prepend[Accumulate[sequence],0];

rect=MapThread[{Rectangle[{accSequence[[#1]],-7},{accSequence[[#2]],7}],
Text[Style[#3,10,Bold,Red],{accSequence[[#1]]+rL/2,0}]}&,{{4,8},{5,9},{"PIDController","LinearSystem"}}];

line1=Line[{{accSequence[[7]],0},{accSequence[[8]],0}}];

circles=Circle[{accSequence[[#]]+rC,0},5]&/@{2,6,10};

arrowsH=
MapThread[{{accSequence[[#]],0},{accSequence[[#2]],0}}&,{{1,4,5,9,11},{2,3,6,10,12}}];

arrowsV=
MapThread[{{accSequence[[#]]+rC,#2+aL},{accSequence[[#]]+rC,#2}}&,{{6,10},{rC,rC}}];

arrows=Join[arrowsH,arrowsV];

texts={
Text[Style["r",12],{accSequence[[1]]-2,0}],
Text[Style["u",12],{accSequence[[5]]+aL/2,4}],
Text[Style["d",12],{accSequence[[6]]+rC,33}],
Text[Style["m",12],{accSequence[[10]]+rC,33}],
Text[Style["y",12],{accSequence[[12]]+2,0}],
Text[Style["-",12],{accSequence[[3]]+4,4}],
Text[Style["+",12],{accSequence[[#]]-4,4}]&/@{2,6,10},
Text[Style["+",12],{accSequence[[#]]+4,4}]&/@{7,11}
};

Graphics[{texts,circles,line1,,Arrowheads[0.02],
Arrow[#]&/@arrows,EdgeForm[Black],LightGray,rect}]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.